Problems with OBJ + MTL loader from Three.js

0

We are scheduling an educational application for orthogonal projections of polyhedra that are read via the Three.js library's OBJ + MTL loader. The problem is that depending on the OBJ + MTL file, the loader sometimes does not work and we do not know why, because the data seems ok.

The method we are using:

  • Load the polyhedron using the OBJ + MTL loader.
  • The THREE.LineSegments () function is used to get the edges of the polyhedron.
  • The THREE.Geometry () function fromBufferGeometry () is used to copy the geometry of the edges.
  • The problem is in Step 3: depending on the OBJ + MTL data file, the THREE.Geometry () function fromBufferGeometry () returns null.

    Here is an example where everything works: link (all information geometry is passed, axes and projections are determined correctly).

    HereisanexamplewherethereisaproblemwiththeTHREE.Geometry()function.fromBufferGeometry(): link (because it was not possible to copy the geometry of the edges, the projections in the coordinate planes failed).

    Herearethepolyhedrondatathatgivesproblems:

    OBJ:

    ######OBJFileGeneratedbyMeshlab######Objectjohnson-j01-square-pyramid.obj##Vertices:5#Faces:6#####mtllib./johnson-j01-square-pyramid.obj.mtlvn-0.000270-0.281574-0.959539v-0.4444571.160279-7.902924vn-0.996609-0.0008780.082282v-7.610548-2.453604-0.243687vn-0.1058610.9338700.341586v-0.6643515.8607012.143697vn0.9684950.2488920.008435v7.942724-0.476746-0.828161vn0.125332-0.8216820.555996v0.776633-4.0906296.831076#5vertices,0verticesnormalsusemtlmaterial_0f5//52//21//1f5//51//14//4usemtlmaterial_1f2//25//53//3f1//12//23//3f4//41//13//3f5//54//43//3#6faces,0coordstexture#EndofFile

    MTL:

    ##Wavefrontmaterialfile#ConvertedbyMeshlabGroup#newmtlmaterial_0Ka0.2000000.2000000.200000Kd1.0000000.0000000.000000Ks1.0000001.0000001.000000Tr1.000000illum2Ns0.000000newmtlmaterial_1Ka0.2000000.2000000.200000Kd0.0000000.0000001.000000Ks1.0000001.0000001.000000Tr1.000000illum2Ns0.000000

    JavaScript+HTML:

    <!DOCTYPEhtml><html><head><metahttp-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Orthogonal Projections 2</title>
    
        <!-- JavaScript Libraries -->
    
        <script src="threejs.r91/build/three.js"></script>
        <script src="threejs.r91/examples/js/controls/TrackballControls.js"></script>
        <script src="threejs.r91/examples/js/loaders/DDSLoader.js"></script>
        <script src="threejs.r91/examples/js/loaders/MTLLoader.js"></script>
        <script src="threejs.r91/examples/js/loaders/OBJLoader.js"></script>
    
        <!-- ThreeJS Code -->
        <script type="text/javascript">
            var transparency_value = 0;
    
            function MakeQuadrilateral(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4)
            {
               var geo = new THREE.Geometry();
    
                // generate vertices
                geo.vertices.push( new THREE.Vector3(x1,y1,z1));
                geo.vertices.push( new THREE.Vector3(x2,y2,z2));
                geo.vertices.push( new THREE.Vector3(x3,y3,z3));
                geo.vertices.push( new THREE.Vector3(x4,y4,z4));
    
    
                geo.faces.push( new THREE.Face3(0,1,2));
                geo.faces.push( new THREE.Face3(0,2,3));
    
    
                // Return the geometry object
                return geo;
            }
    
    
           // Adds text to the screen
            function makeSpriteText(text)
            {
                var canvas = document.createElement('canvas');
                var size = 256; // CHANGED
                canvas.width = size;
                canvas.height = size;
                var context = canvas.getContext('2d');
                context.fillStyle = '#ffffff'; // CHANGED
                context.textAlign = 'center';
                context.font = '48px Times';
                context.fillText(text, size / 2, size / 2);
    
                var amap = new THREE.Texture(canvas);
                amap.needsUpdate = true;
    
                var mat = new THREE.SpriteMaterial({
                    map: amap,
                    transparent: false,
                    useScreenCoordinates: false,
                    color: 0x0000ff // CHANGED
                });
    
                var sp = new THREE.Sprite(mat);
                return(sp);
            }
    
    
            // Check capabilities, and start if sufficient
            var hasWebGl = (function() {try {return !! window.WebGLRenderingContext &&
                    !! document.createElement('canvas').getContext('experimental-webgl');}
            catch(e){return false;}})();
            var hasCanvas = !! window.CanvasRenderingContext2D; // Converts value to boolean
            var hasVibration = navigator.vibrate;
    
    
            window.onresize = function(event)
            {
                if (loaded == true)
                {
                    loaded = false;
    
                    context0.controls = new THREE.TrackballControls(context0.camera, context0.renderer.domElement);
                    context0.controls.target.set(0, 0, 0);
                    context0.controls.noZoom = false;
                    context0.controls.noPan = true;
                    context0.controls.rotateSpeed = 1.2;
                    context0.controls.dynamicDampingFactor = 0.2;
                    context0.controls.staticMoving = false;
                }
            }
    
            if (hasCanvas)
            {
                document.addEventListener( "DOMContentLoaded", init, false);
            } // End of if()
    
            function init()
            {
                // Setup idiom
                document.getElementById("msgwebglcontext0").innerHTML = "<br>";
    
                /* spawns the objects, scenes, cameras, renderers etc. */
                context0 = {color: 0xccff33, name: "0", width: 440, height: 440, factor: 30, arrowLength: 25};
    
                // set the scene
                if (hasWebGl)
                {
                    context0.renderer = new THREE.WebGLRenderer({alpha: true, antialias: true });
                }
                else
                {
                    context0.renderer = new THREE.CanvasRenderer({alpha: true, antialias: true });
                }
                context0.renderer.setSize(context0.width, context0.height);
    
                // Add the renderer to the document.
                // This should be called before THREE.TrackballControls().
                document.getElementById("webglcontext0").appendChild(context0.renderer.domElement);
    
                context0.scene = new THREE.Scene();
                context0.camera = new THREE.PerspectiveCamera(20, context0.height/context0.width, 2, 10000);   // 20: small values cause z-buffer fighting
                context0.camera.position.z = 70;
                context0.camera.position.x = 70;
                context0.camera.position.y = 70;
                context0.scene.add(context0.camera);
                context0.controls = new THREE.TrackballControls(context0.camera, context0.renderer.domElement);
                context0.controls.target.set(0, 0, 0);
                context0.controls.noZoom = false;
                context0.controls.noPan = true;
    
                // Model
                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 ) { };
                THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
                var mtlLoader = new THREE.MTLLoader();
                mtlLoader.setPath( 'obj/' );
                mtlLoader.load( 'johnson-j01-square-pyramid.obj.mtl', function( materials ) {
                    materials.preload();
                    var objLoader = new THREE.OBJLoader();
                    objLoader.setMaterials( materials );
                    objLoader.setPath( 'obj/' );
                    objLoader.load( 'johnson-j01-square-pyramid.obj', function ( object )
                                {
    
                                            object.traverse(function (child)
                                            {
                                                if (child instanceof THREE.Mesh)
                                                {
                                                    // Polyhedra
                                                    child.name = "pdp-faces";
                                                    context0.scene.add(child);
                                                    var geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
                                                    console.log('From loaded OBJ: ' + geometry.vertices.length);
    
                                                    if ( Array.isArray( child.material ) )
                                                    {
                                                        var n = child.material.length;
                                                        for (i = 0; i < n; i++)
                                                        {
                                                           child.material[i].transparent = true;
                                                           child.material[i].opacity = (1 - transparency_value/100.0);
                                                        };
                                                    }
                                                    else
                                                    {
                                                           child.material.transparent = true;
                                                           child.material.opacity = (1 - transparency_value/100.0);
                                                    }
    
                                                    // Edges
                                                    var edges = new THREE.LineSegments(new THREE.EdgesGeometry(child.geometry), new THREE.LineBasicMaterial( {color: 0x000000}) );
                                                    edges.name = "pdp-edges";
                                                    context0.scene.add(edges);
    
                                                    // Vertices
                                                    var geometry = new THREE.Geometry().fromBufferGeometry( edges.geometry );
                                                    console.log('Geometry vertices length: ' + geometry.vertices.length);
                                                    var vertices = [];
                                                    var isNew;
                                                    var tolerance = 0.0000001;
                                                    if (geometry.vertices.length > 0)
                                                    {
                                                        vertices.push(new THREE.Vector3(geometry.vertices[0].x, geometry.vertices[0].y, geometry.vertices[0].z));
                                                    }
                                                    for (i = 1; i < geometry.vertices.length; i++)
                                                    {
                                                        l = vertices.length;
                                                        isNew = true;
                                                        for (j = 0; j < l; j++)
                                                        {
                                                            var d = geometry.vertices[i].distanceTo(vertices[j]);
                                                            if (d < tolerance)
                                                            {
                                                                isNew = false;
                                                            }
                                                        }
                                                        if (isNew == true)
                                                        {
                                                            vertices.push(new THREE.Vector3(geometry.vertices[i].x, geometry.vertices[i].y, geometry.vertices[i].z));
                                                        }
                                                    }
    
    /*
                                                    alert('Unique vertices: ' + vertices.length);
    
                                                    for (i = 0; i < vertices.length; i++)
                                                    {
                                                        alert(vertices[i].x);
                                                    }
    */
                                                    // https://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/Polyhedra.html
                                                    // https://stemkoski.github.io/Three.js/Polyhedra.html
    
                                                    // Fit screen
                                                    child.geometry.computeBoundingSphere();
                                                    var fov = context0.camera.fov * ( Math.PI / 180 );
                                                    var objectSize = child.geometry.boundingSphere.radius;
                                                    var distance = 0.7*Math.abs( objectSize / Math.sin( fov / 2 ) );
                                                    context0.camera.position.z = 2.5*distance;
                                                    context0.camera.position.x = 2.5*distance;
                                                    context0.camera.position.y = 2.5*distance;
    
                                                    // PLANE PROJECTIONS
                                                    var geometry_xy =  new THREE.Geometry().fromBufferGeometry( edges.geometry );
                                                    var geometry_xz =  new THREE.Geometry().fromBufferGeometry( edges.geometry );
                                                    var geometry_yz =  new THREE.Geometry().fromBufferGeometry( edges.geometry );
                                                    geometry_xy.dynamic = true;
                                                    geometry_xz.dynamic = true;
                                                    geometry_yz.dynamic = true;
                                                    for (i = 0; i < geometry_xy.vertices.length; i++)
                                                    {
                                                        var xOld = geometry_xy.vertices[i].x;
                                                        var yOld = geometry_xy.vertices[i].y;
                                                        var zOld = geometry_xy.vertices[i].z;
                                                        geometry_xy.vertices[i].set(xOld, yOld, -distance/3);
                                                        geometry_xz.vertices[i].set(xOld, -distance/3, zOld);
                                                        geometry_yz.vertices[i].set(-distance/3, yOld, zOld);
                                                        // console.log(geometry_xy.vertices[i].x + ' ' + geometry_xy.vertices[i].y + ' ' + geometry_xy.vertices[i].z);
                                                    }
                                                    geometry_xy.verticesNeedUpdate = true;
                                                    geometry_xz.verticesNeedUpdate = true;
                                                    geometry_yz.verticesNeedUpdate = true;
    
    
                                                    var edges_xy = new THREE.LineSegments(geometry_xy, new THREE.LineBasicMaterial( {color: 0x000000}) );
                                                    var edges_xz = new THREE.LineSegments(geometry_xz, new THREE.LineBasicMaterial( {color: 0x000000}) );
                                                    var edges_yz = new THREE.LineSegments(geometry_yz, new THREE.LineBasicMaterial( {color: 0x000000}) );
                                                    edges_xy.name = "pdp-edges-xy";
                                                    edges_xz.name = "pdp-edges-xz";
                                                    edges_yz.name = "pdp-edges-yz";
                                                    context0.scene.add(edges_xy);
                                                    context0.scene.add(edges_xz);
                                                    context0.scene.add(edges_yz);
    
    
                                                    // VERTICES
                                                    var vertexGeometry = new THREE.SphereGeometry(child.geometry.boundingSphere.radius/35.0, 12, 6 );
                                                    var vertexMaterial = new THREE.MeshBasicMaterial( { color: 0x000000 } );
                                                    var vertexSingleMesh = new THREE.Mesh( vertexGeometry );
                                                    var vertexAmalgam = new THREE.Geometry();
                                                    for (var i = 0; i < vertices.length; i++)
                                                    {
                                                        var vMesh = vertexSingleMesh.clone();
                                                        vMesh.position.set(vertices[i].x, vertices[i].y, vertices[i].z);
                                                        THREE.GeometryUtils.merge( vertexAmalgam, vMesh );
                                                    }
                                                    var vertexMesh = new THREE.Mesh( vertexAmalgam, vertexMaterial );
                                                    vertexMesh.name = "pdp-vertices";
                                                    context0.scene.add(vertexMesh);
                                                    context0.scene.getObjectByName("pdp-vertices").visible = false;
    
    
                                                    // PLANES
                                                    var d = distance/3;
                                                    var xyGeometry = MakeQuadrilateral( d, -d, -d,
                                                                                        d,  d, -d,
                                                                                       -d,  d, -d,
                                                                                       -d, -d, -d);
                                                    var xyPlane = new THREE.Mesh(xyGeometry, new THREE.MeshBasicMaterial({color: 0x090909, side: THREE.DoubleSide, opacity: 0.2, transparent: true }));
                                                    xyPlane.name = "xyPlane";
                                                    context0.scene.add(xyPlane);
    
                                                    var d = distance/3;
                                                    var xzGeometry = MakeQuadrilateral(  d, -d,  d,
                                                                                         d, -d, -d,
                                                                                        -d, -d, -d,
                                                                                        -d, -d,  d);
                                                    var xzPlane = new THREE.Mesh(xzGeometry, new THREE.MeshBasicMaterial({color: 0x090909, side: THREE.DoubleSide, opacity: 0.2, transparent: true }));
                                                    xzPlane.name = "xzPlane";
                                                    context0.scene.add(xzPlane);
    
                                                    var d = distance/3;
                                                    var yzGeometry = MakeQuadrilateral( -d, -d,  d,
                                                                                        -d, -d, -d,
                                                                                        -d,  d, -d,
                                                                                        -d,  d,  d);
                                                    var yzPlane = new THREE.Mesh(yzGeometry, new THREE.MeshBasicMaterial({color: 0x090909, side: THREE.DoubleSide, opacity: 0.2, transparent: true }));
                                                    yzPlane.name = "yzPlane";
                                                    context0.scene.add(yzPlane);
    
    
                                                    // AXES
                                                    var xVector = new THREE.ArrowHelper(new THREE.Vector3(1, 0, 0),
                                                                    new THREE.Vector3(-d, -d, -d ),
                                                                    2*d + 0.5*d, 0x0000ff, 0.2*d, 0.1*d);
                                                    xVector.name = "xVector";
                                                    xVector.line.visible = true;
                                                    xVector.cone.visible = true;
                                                    context0.scene.add( xVector );
                                                    var xLabel = makeSpriteText("y");
                                                    xLabel.name = "xLabel";
                                                    xLabel.position.set(d + 0.7*d, -d, -d);
                                                    xLabel.scale.set( d, d, d );
                                                    context0.scene.add(xLabel);
    
                                                    var yVector = new THREE.ArrowHelper(new THREE.Vector3(0, 1, 0),
                                                                    new THREE.Vector3(-d, -d, -d),
                                                                    2*d + 0.5*d, 0x0000ff, 0.2*d, 0.1*d);
                                                    yVector.name = "yVector";
                                                    yVector.line.visible = true;
                                                    yVector.cone.visible = true;
                                                    context0.scene.add(yVector );
                                                    var yLabel = makeSpriteText("z");
                                                    yLabel.name = "yLabel";
                                                    yLabel.position.set(-d, d + 0.6*d, -d);
                                                    yLabel.scale.set( 10, 10, 10 );
                                                    context0.scene.add(yLabel);
    
                                                    var zVector = new THREE.ArrowHelper(new THREE.Vector3(0, 0, 1),
                                                                    new THREE.Vector3(-d, -d, -d),
                                                                    2*d + 0.5*d, 0x0000ff, 0.2*d, 0.1*d);
                                                    zVector.name = "zVector";
                                                    zVector.line.visible = true;
                                                    zVector.cone.visible = true;
                                                    context0.scene.add(zVector );
                                                    var zLabel = makeSpriteText("x");
                                                    zLabel.name = "zLabel";
                                                    zLabel.position.set(-d, -d, d + 0.7*d);
                                                    zLabel.scale.set( 10, 10, 10 );
                                                    context0.scene.add(zLabel);
    
                                                }
    
                                            });
    
                    }, onProgress, onError );
                });
    
    
    
                // var ambLight = new THREE.AmbientLight(0x404040);
                // context0.scene.add(ambLight);
                context0.light = new THREE.DirectionalLight(0xffffff, 1);
                context0.light.position = context0.camera.position;
                context0.scene.add(context0.light);
    
    
    
                // Run
                context0.camera.updateProjectionMatrix();
                render();
                animate();
    
                loaded = true;
            } // End of init()
    
            function animate()
            {
                /* One animation tick */
                requestAnimationFrame(animate);
                context0.controls.update();
                render();
            } // End of animate()
    
            function render()
            {
                /* renders our little scene */
                context0.renderer.render(context0.scene, context0.camera);
            } // End of render()
    
    
    </script>
    
    </head>
    <body> <!--    <body onload='disableScroll();'>         -->
    <center>
    <span id="webglcontext0" style="width:410px; height:50px; display: table-cell; text-align:center; vertical-align: middle; border-style: solid; border-width: 1px;"></span>
    <div id="msgwebglcontext0" style="text-align:center; display: table; margin-left: -3px;">
    <span style="width:743px; height:30px; display: table-cell; text-align:justify; padding:10px; vertical-align: middle; border-style: solid; border-width: 1px;">
    Por favor, espere o navegador carregar a página. Caso
        isto já tenha acontecido e o applet abaixo não executou, isto significa que seu navegador parece não suportar WebGL ou esta opção não está habilitada.
    Em caso de dúvidas, entre em contato conosco pelo e-mail:
    <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#99;&#111;&#110;&#116;&#101;&#117;&#100;&#111;&#115;&#100;&#105;&#103;&#105;&#116;&#97;&#105;&#115;&#64;&#105;&#109;&#46;&#117;&#102;&#102;&#46;&#98;&#114;">&#99;&#111;&#110;&#116;&#101;&#117;&#100;&#111;&#115;&#100;&#105;&#103;&#105;&#116;&#97;&#105;&#115;&#64;&#105;&#109;&#46;&#117;&#102;&#102;&#46;&#98;&#114;</a>.
    </span>
    </div>
    </center>
    </body>
    </html>
    

    What's going on?

        
    asked by anonymous 26.03.2018 / 19:25

    0 answers