three.jsloader3d-renderingobjloader

Loading Obj with OBJLoader2 to load Vertex Colors


I have an .obj file which has Vertex Colors in it. That is it doesn't have seperate .mtl file for its Texture . The .obj File itself contains the color for each vertex.

I wanted to load it using three.js

I knew I can load a normal .obj file with .mtl using :


 objLoader = new THREE.OBJLoader();
        objLoader.load('meshlabshristi3.obj', function(object) {
            scene.add(object);
        });

But mine has vertex colors so I found it can be done with OBJLoader2.js so tried executing it like :


 var objLoader = new THREE.OBJLoader2();
    objLoader.load('assets/faceimage9.obj', function(object) {
        scene.add(object);
    });

But it throws errors saying


OBJLoader2.js:6 Uncaught SyntaxError: Cannot use import statement outside a module

index.html:80 Uncaught TypeError: THREE.OBJLoader2 is not a constructor
    at init (index.html:80)
    at index.html:31

Am I doing it wrong or is there any other problem . Can anyone post the exact code to load a vertex colored mesh . Thanks in advance for anyone who tried to read and solve it ...

If anyone need a vertex colored mesh to work on I had attached below.. Vertex Colored Model

For the comment below I attach this image:

enter image description here


Solution

  • Both OBJLoader and OBJLoader2 seem work just fine.

    You just need to set material.vertexColors = true on all the materials (or all the ones that have vertex colors)

    objLoader.load('assets/faceimage9.obj', function(object) {
      scene.add(object);
      object.traverse(node => {
        if (node.material) {
          node.material.vertexColors = true;
        }
      });
    });
    

    html, body {
      margin: 0;
      height: 100%;
    }
    #c {
      width: 100%;
      height: 100%;
      display: block;
    }
    <canvas id="c"></canvas>
    <script type="module">
    // Three.js - Load .OBJ 
    // from https://threejsfundamentals.org/threejs/threejs-load-obj-auto-camera-xz.html
    
    import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/build/three.module.js';
    import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/controls/OrbitControls.js';
    import {OBJLoader2} from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/loaders/OBJLoader2.js';
    
    function main() {
      const canvas = document.querySelector('#c');
      const renderer = new THREE.WebGLRenderer({canvas});
    
      const fov = 45;
      const aspect = 2;  // the canvas default
      const near = 0.1;
      const far = 50;
      const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
      camera.position.set(0, 0, 0.7);
    
      const controls = new OrbitControls(camera, canvas);
      controls.target.set(0, 0, 0);
      controls.update();
    
      const scene = new THREE.Scene();
      scene.background = new THREE.Color('white');
    
      {
        const skyColor = 0xB1E1FF;  // light blue
        const groundColor = 0xB97A20;  // brownish orange
        const intensity = 1;
        const light = new THREE.HemisphereLight(skyColor, groundColor, intensity);
        scene.add(light);
      }
    
      {
        const color = 0xFFFFFF;
        const intensity = 1;
        const light = new THREE.DirectionalLight(color, intensity);
        light.position.set(5, 10, 2);
        scene.add(light);
        scene.add(light.target);
      }
    
      {
        const objLoader = new OBJLoader2();
        // note: this model is CC-BY-NC 4.0 from
        // here: https://sketchfab.com/3d-models/book-vertex-chameleon-study-51b0b3bdcd844a9e951a9ede6f192da8
        // by: Oleaf (https://sketchfab.com/homkahom0)
        objLoader.load('https://greggman.github.io/doodles/models/book-vertex-chameleon-study/book.obj', (root) => {
          scene.add(root);
          root.updateMatrixWorld();
          root.traverse(node => {
            if (node.material) {
              if (Array.isArray(node.material)) {
                node.material.forEach(m => m.vertexColors = true);
              } else {
                node.material.vertexColors = true;
              }
            }
          })
        });
      }
    
      function resizeRendererToDisplaySize(renderer) {
        const canvas = renderer.domElement;
        const width = canvas.clientWidth;
        const height = canvas.clientHeight;
        const needResize = canvas.width !== width || canvas.height !== height;
        if (needResize) {
          renderer.setSize(width, height, false);
        }
        return needResize;
      }
    
      function render() {
    
        if (resizeRendererToDisplaySize(renderer)) {
          const canvas = renderer.domElement;
          camera.aspect = canvas.clientWidth / canvas.clientHeight;
          camera.updateProjectionMatrix();
        }
    
        renderer.render(scene, camera);
    
        requestAnimationFrame(render);
      }
    
      requestAnimationFrame(render);
    }
    
    main();
    </script>

    As for the error

    OBJLoader2.js:6 Uncaught SyntaxError: Cannot use import statement outside a module

    If you're using ES6 modules you need to put your script in <script type="module"> script tag, and organize the files the same as they are organized in the three.js repo. Namely

    +-somefolder
      |
      +-build
      |  |
      |  +-three.module.js
      |
      +-examples
        |
        +-jsm
          |
          +-controls
          | |
          | +-OrbitControls.js (if you're using this)
          |
          +-loaders
            |
            +-OBJLoader2.js
    

    And then use import statements to load everything

    <script type="module">
    import * as THREE from 'somefolder/build/three.module.js';
    import {OrbitControls} from 'somefolder/examples/jsm/controls/OrbitControls.js';
    import {OBJLoader2} from 'somefolder/examples/jsm/loaders/OBJLoader2.js';
    ...
    

    See: this answer

    If you want to do it the old deprecated way with a multiple script tags instead of import then use the files from examples/js instead of examples/jsm in which case you can put them anywhere but assuming you keep them in the same place then

    <script src="somefolder/build/three.min.js"></script>
    <script src="somefolder/examples/js/controls/OrbitControls.js"></script>
    <script src="somefolder/examples/js/loaders/OBJLoader2.js"></script>
    

    Note it uses three.min.js not three.module.js