Problems with OBJ + MTL Three.js Download

Asked

Viewed 214 times

0

We are programming an educational application for orthogonal projections of polyhedra that are read via the Three.js library’s Loader OBJ+MTL. The problem is that depending on the OBJ+MTL file, the Upload sometimes doesn’t work and we don’t know why, because the data seems ok.

The method we’re using:

  1. Load polyhedron using OBJ + MTL Download.
  2. The THREE.Linesegments() function is used to obtain the edges of the polyhedron.
  3. The THREE.Geometry(). fromBufferGeometry() function is used to copy edge geometry.

The problem is in Step 3: depending on the OBJ+MTL data file, the THREE.Geometry() function. fromBufferGeometry() returns null.

Here’s an example where everything works: http://www.im-uff.mat.br/tmp/how/simple-01.html (all geometric information is passed, axes and projections are determined correctly).

inserir a descrição da imagem aqui

Here is an example where there is a problem with the function THREE.Geometry(). fromBufferGeometry(): http://www.im-uff.mat.br/tmp/how/simple-02.html (as it was not possible to copy the geometry of the edges, the projections in the coordinated planes failed).

inserir a descrição da imagem aqui

Here are the data of the polyhedron that gives problems:

OBJ:

####
#
# OBJ File Generated by Meshlab
#
####
# Object johnson-j01-square-pyramid.obj
#
# Vertices: 5
# Faces: 6
#
####
mtllib ./johnson-j01-square-pyramid.obj.mtl

vn -0.000270 -0.281574 -0.959539
v -0.444457 1.160279 -7.902924 
vn -0.996609 -0.000878 0.082282
v -7.610548 -2.453604 -0.243687
vn -0.105861 0.933870 0.341586
v -0.664351 5.860701 2.143697
vn 0.968495 0.248892 0.008435
v 7.942724 -0.476746 -0.828161
vn 0.125332 -0.821682 0.555996
v 0.776633 -4.090629 6.831076
# 5 vertices, 0 vertices normals

usemtl material_0
f 5//5 2//2 1//1
f 5//5 1//1 4//4

usemtl material_1
f 2//2 5//5 3//3
f 1//1 2//2 3//3
f 4//4 1//1 3//3
f 5//5 4//4 3//3
# 6 faces, 0 coords texture

# End of File

MTL:

#
# Wavefront material file
# Converted by Meshlab Group
#

newmtl material_0
Ka 0.200000 0.200000 0.200000
Kd 1.000000 0.000000 0.000000
Ks 1.000000 1.000000 1.000000
Tr 1.000000
illum 2
Ns 0.000000

newmtl material_1
Ka 0.200000 0.200000 0.200000
Kd 0.000000 0.000000 1.000000
Ks 1.000000 1.000000 1.000000
Tr 1.000000
illum 2
Ns 0.000000

Javascript + HTML:

<!DOCTYPE html>
<html>
<head>
    <meta http-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>

I wonder what’s going on?

  • Three-dimensional files, have several versions, you need to treat them first in some tool like Blender, and export all in the same version.

  • @Sveen, I did this with Meshlab and yet the problem continues. What’s more, the 3D data files seem to follow the specifications. Will is a bug the Three.js?

  • https://www.dropbox.com/s/woprbi70pc93uoz/johnson-j01-square-pyramid.rar?dl=0 tries to use this

  • @Sveen, unfortunately the problem continues: http://www.im-uff.mat.br/tmp/how/simple-03.html. Is this a library bug? Who to contact in this case?

  • If you have alpha, it probably can be, but try to find in the documentation how you recover errors, if you cannot, request

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.