Having issues with loading THREE.js object within a Vue component

I'm baffled by the interaction between vue and THREE.js. I have the same object that works fine in a plain JS environment but not in vue.js. The canvas remains empty in vue.js and the developer console displays multiple warnings.

The code I used in JS is identical to the code in vue (see below). I have also included a screenshot of the warnings I received in Chrome's developer tools.

I suspect that the issue is related to the path to the OBJ file, as some unexpected lines are clearly not from an HTML file. I have tried different alternatives such as "./assets/threeD/harrie.obj" or using

let ha = require("../assets/threeD/harrie.obj");
, but the latter causes a compilation error as shown 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 does not resolve the issue, the error just moves to the next line with content.

What's most perplexing is that some sort of geometry seems to be loading, but regardless of the camera's scaling or rotation, the canvas remains empty. THREE was installed via npm

https://i.sstatic.net/rGyNY.png

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>

Answer №1

When working with Vue apps, it's important to note that your code will go through a webpack compilation process before it can be run. Typically, the root of your application will be located at /dist/index.html. This means that the URL you originally provided will not be valid, causing the server to return an HTML page and resulting in the error message shown in your screenshot.

To correctly reference the model, you should start by importing it:

import model from '../assets/models/example.obj'

The variable model will contain the final URL, which can then be used to load the model:

loader.load(model, ...

However, you may also need to provide webpack with instructions on how to handle an .obj file, as webpack might not automatically include them in the bundle. Adding a file loader rule that includes .obj files should resolve this issue. Here's an example of how you can set up the rule:

{
   test: /\.(png|jpg|gif|mp4|ogg|svg|woff|woff2|ttf|eot|glb|obj|gltf|hdr)$/,
   loader: 'file-loader'
},

Answer №2

I'm working on a project using ThreeJS, Vue3, and Vite, and I'm happy to say that the code is up and running smoothly. Feel free to take a look!

src
├── assets
│   └── models
│       └── glb
│            └── Totoro.glb
└── components
    └── Sample6Modeling.vue

Sample6Modeling.vue

const loader = new GLTFLoader();
const modelUrl = new URL('../assets/models/glb/Totoro.glb', import.meta.url).href;
loader.load( modelUrl, 
     function ( gltf ) {scene.add( gltf.scene )}, 
     undefined, 
     function ( error ) { console.error( error )}
);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to test the output of HTML code in a unit test scenario

I am new to web development and testing, taking it slow. I have a website with a button that reveals information when clicked. How can I create a test case to ensure that the displayed output is correct? I need to verify that the text appears on the scre ...

Receive notification of alert content when it is displayed

Having an HTML page with the following script: <Script> function Run() { alert("The Content Here"); return true; } </script> <button onclick="Run();">I Want It Now</button> If I were to open this page using firefox or Chrome, and ...

Acquire the "value" and utilize it within a different function

I am facing a minor issue with my JavaScript code. I have been working on creating a gallery page. In this page, there is an icon that triggers a function called "comment" when clicked. function comment() { var div = document.getElementById("commentdiv") ...

Navigating global variables and functions in Vue3 with TypeScript

Feeling lost in the world of Vue.js, seeking guidance here. Attempting to handle global data and its corresponding functions has led me on a journey. Initially, I experimented with declaring a global variable. But as more functions came into play, I trans ...

Remove an item from a complex JSON structure based on the specified name. The function will then return the

Hey there, I'm just starting out with react native and I have an array of objects. My goal is to remove an inner object from this JSON data. [ { Key: 1, exchnageArr: [ { name: ”FX” }, { name: ”MK” ...

Ways to bypass a transition using JavaScript

Hello everyone, I would like to start by apologizing for any mistakes in my English. I have been working on a website, which is currently available here: As you scroll down, the height of the image below the menu decreases. I am trying to make the navig ...

Issue with Node/Express: Middleware addition to router does not function as expected

Here is the configuration of my router: app.get('/getReport', (req, res) => { res.send("This is the report"); }); Initially, this router functions properly and successfully displays the message This is the report in the browser However, ...

Display the count of ng-repeat items beyond its scope

Currently, I am looping through a list of nested JSON objects in this manner: <div ng-repeat='item in items'> <ul> <li ng-repeat='specific in item'>{{specific}}</li> </ul> </div> I want to ...

Is it possible to utilize a JS script generated within the body or head of an HTML file directly within CSS code?

As a beginner in webpage development, I have a query regarding the technical aspect. Is it possible to utilize variables from a JavaScript function, which is placed either in the head or body of an HTML file, directly in CSS code to make modifications such ...

Incorporate an external object not native to the Angular framework within a factory

We're in the midst of a debate and I'm hoping you can help us reach an agreement. Imagine I have a basic factory set up like this: angular.module('myModule', []) .factory('Fact', function() { var Fact = function() { ...

Hide the button when you're not actively moving the mouse, and show it when you start moving it

How can I make my fixed positioned button only visible when the mouse is moved, and otherwise hidden? ...

Accessing data returned from JSON in JQuery beyond the code block required

Is there a way to access returned JSON data outside of the JQuery getJSON method? For example: var price = ""; $.getJSON("../JSONDeliveryPrice", null, function (data) { price = eval(data.price); }); console.log(price); Unfortunately, this code does not ...

The port is not defined in the express when running with the command "node ."

After going through the tutorial mentioned here, everything was smooth sailing until I reached the part where I had to run the server: https://www.digitalocean.com/community/tutorials/setting-up-a-node-project-with-typescript Attempting to execute the cod ...

Organize an array based on its ratio

I am attempting to organize an array based on the win and lose ratio of each player. This is how my code currently looks: const array = [{playerName: 'toto', win: 2, lose: 2}, {playerName: 'titi', win: 0, lose: 0}, {playerName: &apo ...

Modifying an item in a list using React and Redux

I am facing an issue with my table that consists of 50 rows, each representing an item from a list. When I click on a checkbox within a row, I want to mark that specific item as selected. However, the problem is that clicking on any checkbox causes all 50 ...

Adding and removing dynamic fields with Bootstrap functionality

Recently, I've been trying to develop a feature where users can add and remove fields by clicking on a button. However, I've encountered a roadblock in my progress. If you take a look at this CodePen link, you'll see what I have so far. My a ...

Tips for creating an effective planar reflection using Open Graphics Library (OGL) in conjunction with a perspective camera

I'm attempting to create a mirror-like reflection of a WebGL scene on a plane using ogl, similar to how a mirror would behave. I tried implementing a basic version of the three.js reflector but ended up with a distorted image that doesn't accurat ...

Is there a way to retrieve the current route on a custom 404 page in Next.JS?

I have set up a custom 404 page for my Next.JS application (404.js). I want to display a message stating The route <strong>/not-a-route</strong> does not exist, but when I use Next.js's useRouter() and router.pathname, it incorrectly ident ...

Combine the selected values of two dropdowns and display the result in an input field using Angular

I am working on a component that consists of 2 dropdowns. Below is the HTML code snippet for this component: <div class="form-group"> <label>{{l("RoomType")}}</label> <p-dropdown [disabled] = "!roomTypes.length" [options]= ...