Skip to content
Advertisement

THREE.js obj not loading in vue

I’m really confused about the way vue and THREE.js work together. I am using the exact same obj, once in a plain js environment – where it works perfectly fine – and once in vue.js, where the canvas stays empty and the dev console shows several warnings.

The code I used in js is the exact same as in vue (see below). I also attached a screenshot of the warnings I get in the developer tool from chrome.

I assume the problem is related to the path to the OBJ since some unexpected lines are clearly out of a HTML file. I also tried various alternatives like "./assets/threeD/harrie.obj" or using let ha = require("../assets/threeD/harrie.obj");, however the latter causes a compilation error as below:

Failed to compile.

 ./src/assets/threeD/harrie.obj 1:0
Module parse failed: Unexpected character '#' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> # This file uses centimeters as units for non-parametric coordinates.
| 
| v -1.860180 5.269862 2.275461

Deleting the first line doesn’t change anything, the error just shifts to the next line with content

The most confusing thing however is that some kind of geometry seems to get loaded, however no matter the scaling or rotation of the camera, there is absolutely nothing in the canvas. THREE was installed via npm

right: Warnings in dev, left: folder structure

import * as THREE from "three";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
import {OBJLoader} from "three/examples/jsm/loaders/OBJLoader";

export default {
  name: "Project1",
  data: function () {
    return {
      mesh: null
    }
  },
  methods: {
    harriethree: function () {
      let w = document.getElementById("threejsview").offsetWidth;
      let h = document.getElementById("threejsview").offsetHeight;
      const sceneContainer = document.getElementById("threejsview");
      const container = document.getElementById("scene");
      document.body.appendChild(container);

      let scene, camera, renderer, loader;

      scene = new THREE.Scene();
      scene.background = new THREE.Color('#1d1c1c');
      camera = new THREE.PerspectiveCamera(75, w / h, 0.1, 1000);
      camera.translateX(-10);


      renderer = new THREE.WebGLRenderer();
      renderer.setSize(w, h);
      renderer.domElement.id = "harrieCanvas";
      sceneContainer.appendChild(renderer.domElement);

      let directionalLight = new THREE.DirectionalLight("white", 1);
      scene.add(directionalLight);

      let orb = new OrbitControls(camera, renderer.domElement);
      orb.update();

      loader = new OBJLoader();
      loader.load("../assets/threeD/harrie.obj", (obj) => {
        scene.add(obj);
        console.log(obj);
        renderer.render(scene, camera);
      })

      animate();

      function animate() {

        requestAnimationFrame(animate);

        // required if controls.enableDamping or controls.autoRotate are set to true
        orb.update();

        renderer.render(scene, camera);
      }
    }
  },
  mounted() {
    this.$nextTick(function () {
      this.harriethree();
    })
  }
}
#pro1Top {
  margin: 20vh 2vw 20vh 2vw;
  display: grid;
  grid-template-columns: 47vw 47vw;
  grid-template-rows: 80vh 80vh;
  grid-column-gap: 2vw;
}

#threejsview {
  grid-row: 1 /span 1;
  grid-column: 1 /span 1;
  width: 100%;
  height: 100%;
}

#pro1content {
  grid-row: 1 /span 2;
  grid-column: 2 /span 1;
  background-color: green;
}
<template>
  <div id="pro1Top">
    <div id="threejsview">
      <div id="scene"></div>
    </div>
    <div id="pro1content">
      <h1>Harrie</h1>
      <p>Harrie was created during</p>
    </div>
  </div>
</template>

Advertisement

Answer

in vue apps, your code will be compiled by webpack before running. the root of your app will usually be /dist/index.html, so the url you provided will not be a valid one, which cause the server return a html page, hence the error message in your screenshot.

to properly point to the model, you should first import the model:

import ha from '../assets/threeD/harrie.obj'

this ha will be the final url, use it to load the model:

loader.load(ha, ...

but you will probably need to give webpack instruction on how to handle an object file, otherwise webpack will not include them in the bundle. add a file loader rule which includes obj will do the trick, should be something like this:

{
   test: /.(png|jpg|gif|mp4|ogg|svg|woff|woff2|ttf|eot|glb|obj|gltf|hdr)$/,
   loader: 'file-loader'
},
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement