OBJ and MTL File not displaying properly

Hi,

I’m new to three.js and I’m trying to use the example orbit controls to view a model that is an obj and mtl file with orbit controls. I’m basing this on the orbit controls example. Here’s my code:

<!DOCTYPE html>

<html lang="en">

    <head>

        <title>three.js webgl - orbit controls</title>

        <meta charset="utf-8">

        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">

        <link type="text/css" rel="stylesheet" href="main.css">

        <style>

            body {

                background-color: #ccc;

                color: #000;

            }

            a {

                color: #f00;

            }

        </style>

    </head>

    <body>

        <div id="info">

            <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - orbit controls

        </div>

        <script type="module">

            import * as THREE from '../build/three.module.js';

            import { OrbitControls } from './jsm/controls/OrbitControls.js';

            import { OBJLoader2 } from './jsm/loaders/OBJLoader2.js';

            import { MTLLoader } from './jsm/loaders/MTLLoader.js';

            import { MtlObjBridge } from './jsm/loaders/obj2/bridge/MtlObjBridge.js';

            var camera, controls, scene, renderer;

            init();

            //render(); // remove when using next line for animation loop (requestAnimationFrame)

            animate();

            function init() {

                scene = new THREE.Scene();

                scene.background = new THREE.Color( 0xcccccc );

                scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );

                renderer = new THREE.WebGLRenderer( { antialias: true } );

                renderer.setPixelRatio( window.devicePixelRatio );

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

                document.body.appendChild( renderer.domElement );

                camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );

                camera.position.set( 400, 200, 0 );

                // controls

                controls = new OrbitControls( camera, renderer.domElement );

                //controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)

                controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled

                controls.dampingFactor = 0.05;

                controls.screenSpacePanning = false;

                controls.minDistance = 100;

                controls.maxDistance = 500;

                controls.maxPolarAngle = Math.PI / 2;

                // world

                // var geometry = new THREE.CylinderBufferGeometry( 0, 10, 30, 4, 1 );

                // var material = new THREE.MeshPhongMaterial( { color: 0xffffff, flatShading: true } );

                // for ( var i = 0; i < 500; i ++ ) {

                //  var mesh = new THREE.Mesh( geometry, material );

                //  mesh.position.x = Math.random() * 1600 - 800;

                //  mesh.position.y = 0;

                //  mesh.position.z = Math.random() * 1600 - 800;

                //  mesh.updateMatrix();

                //  mesh.matrixAutoUpdate = false;

                //  scene.add( mesh );

                // }

                // truck

                var mtlLoader = new MTLLoader();

                    mtlLoader.load( 'models/truck/truck.mtl', function( materials ) {

                        materials.preload();

                        materials.side = THREE.DoubleSide;

                        const mat = MtlObjBridge.addMaterialsFromMtlLoader(materials);

                        console.log(mat);

                        var objLoader = new OBJLoader2();

                        objLoader.addMaterials( mat );

                        objLoader.load( 'models/truck/truck.obj', function ( object ) {

                            console.log(object);

                            object.position.y = - 95;

                            scene.add( object );

                        } );

                    });

                // var loader = new OBJLoader();

                // loader.load( 'models/truck/truck.obj', function ( obj ) {

                //  // center asset

                //  var box = new THREE.Box3().setFromObject( obj );

                //  var center = new THREE.Vector3();

                //  box.getCenter( center );

                //  obj.position.sub( center );

                //  // add to scene

                //  scene.add( obj );

                // } );

                // lights

                var light = new THREE.DirectionalLight( 0xffffff );

                light.position.set( 1, 1, 1 );

                scene.add( light );

                var light = new THREE.DirectionalLight( 0x002288 );

                light.position.set( - 1, - 1, - 1 );

                scene.add( light );

                var light = new THREE.AmbientLight( 0x222222 );

                scene.add( light );

                //

                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(); // only required if controls.enableDamping = true, or if controls.autoRotate = true

                render();

            }

            function render() {

                renderer.render( scene, camera );

            }

        </script>

    </body>

</html>

Here’s the result:

Two questions here. First, why does it look like this? I don’t see any errors or warnings in the console, and here’s the exact same file loaded into 3DS Max:

What could I be doing wrong that only parts of the model show?

Lastly, the origin seems to be set incorrectly. In this case, on the “hood” of the truck, how can I flip it so that it orbits on the “ground” normal to the tires?

Thanks!

With regard to glTF, OBJ and MTL are actually deprecated and should not be used anymore. Can you please export the Cybertruck to glTF instead?

Using glTF will not only speed up the loading process, it will also simplify your code.

Fair enough. Are there any conversion methods you recommend? Preferably ones that can be automated? We have quite a few OBJ assets.

I see this one: https://github.com/CesiumGS/obj2gltf but have no experience with it. Thanks!

Yeah, I would start with this tool, too. It’s also in the list of the Loading 3D models guide.

https://threejs.org/docs/index.html#manual/en/introduction/Loading-3D-models

When I look at your model of the tesla ute.
I notice the transparencies.
When you export the model from your 3d program (I don’t recognise the program), it creates the mtl file along side the obj. I have seen some times transparency settings not property written to an mtl the way I expected it to when exporting from blender, so then when you load it in threejs, it’s either completely transparent or not.
You may also have a frontside/backside issue.

In this video I look at the various properties of an mtl file, and how they are translated from blender into threejs. There may be some clue for you in this.