Error message: The object is not visible due to the removal of .shading in THREE.MeshPhongMaterial by three-mtl-loader

Yesterday I posted a question on StackOverflow about an issue with my code (Uncaught TypeError: THREE.MTLLoader is not a constructor 2.0). Initially, I thought I had solved the problem but now new questions have surfaced:

Even though I have installed 'three-mtl-loader' using npm, the object doesn't seem to be visible, despite being able to confirm its existence through console.log.

Now, I am encountering the following error, which might be the reason for the object's invisibility:

 THREE.MeshPhongMaterial: .shading has been removed. Use the boolean .flatShading instead.
 get                                @   three.js:43339
 WebGLPrograms.getParameters        @   three.js:17838
 initMaterial                       @   three.js:21734
 setProgram                         @   three.js:21929
 WebGLRenderer.renderBufferDirect   @   three.js:20964
 renderObject                       @   three.js:21722
 renderObjects                      @   three.js:21695
 WebGLRenderer.render               @   three.js:21463
 render                             @   main.ts:163
 requestAnimationFrame (async)      
 render                             @   main.ts:162 
 requestAnimationFrame (async)      
 render                             @   main.ts:162
 requestAnimationFrame (async)  
 ...    

The current state of my code is as follows:

import * as THREE from 'three'
import * as OBJLoader from 'three-obj-loader'
OBJLoader(THREE)
import * as MTLLoader from 'three-mtl-loader'

//create global variables so models can be accessed outside loader functions
var model1, model2;

var mtlLoader = new MTLLoader();
mtlLoader.setPath('http://blabla/objects/');
mtlLoader.load('bla.obj.mtl', function(materials){

  materials.preload();

  var objLoader = new THREE.OBJLoader();  
  objLoader.setMaterials(materials);
  objLoader.setPath('http://blabla/objects/');
  objLoader.load('bla.obj', function(object){

      var object1 = object.clone();
      model1 = object;     
      model2 = object1; 

      scene.add(model1);
      scene.add(model2)

  });
});

I'm unsure if this is similar to another issue discussed here: https://github.com/sohamkamani/three-object-loader/issues/9. For instance, when trying the code snippet:

 let child;
 for(let i = 0; i < object.children.length; i++) {
    child = object.children[i];
    scene.add(new THREE.Mesh(child.geometry, new THREE.MeshPhongMaterial({ })));
}

A white mesh is inserted, but incorporating the mtl-file color like they do in the example seems time-consuming for each mesh individually due to cloning the model for two separate instances. Can object.traverse possibly aid without manual loader modifications?

Any assistance is greatly appreciated :D

EDIT After attempting various solutions unsuccessfully, summarizing the issues below may provide insight into what's missing or misconfigured:

  1. The method mentioned previously isn't solving the problem as delineated in comments. Steps were taken to update to the latest version of three resulting in a persisting error flagged only as a warning, while objects remain unseen. Adjusting to flatshading within the OBJloader resolves the warnings yet visibility remains elusive - sans alterations to file configurations.

    THREE.MeshPhongMaterial: .shading has been removed. Use the boolean .flatShading instead
    set @   three.js:43344
    parse   @   index.js:628
    (anonymous) @   index.js:58
    (anonymous) @   three.js:30483
    XMLHttpRequest.send (async)     
    load    @   three.js:30563
    load    @   index.js:56
    (anonymous) @   main.ts:117
    (anonymous) @   index.js:36
    (anonymous) @   three.js:30090
    XMLHttpRequest.send (async)     
    load    @   three.js:30146
    load    @   index.js:34
    s   @   _prelude.js:1
    e   @   _prelude.js:1
    (anonymous) @   _prelude.js:1
    
  2. Utilizing solely the three-obj-loader functions correctly as demonstrated in this post: Uncaught TypeError: THREE.MTLLoader is not a constructor

  3. Duplicating both the OBJLoader and MTLLoader scripts (https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/OBJLoader.js and https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/MTLLoader.js) into the three/src/loaders directory alongside including these exports in three.js:

    export { MTLLoader} from './loaders/MTLLoader.js' export { OBJoader} from './loaders/OBJLoader.js'

Subsequently loading them as depicted below:

import {MTLLoader} from 'three'
import {OBJLoader} from 'three'

Results in a

Uncaught TypeError: THREE.MTLLoader is not a constructor
, wherein checks of console.log(MTLLoader) and console.log(OBJLoader) return undefined statuses. Perhaps, they're incorrectly integrated within the framework since web-based reference scenarios are abundant (
<script src="js/loaders/OBJLoader.js"></script>
). Being relatively new to TypeScript, pondering whether establishing a reference path or another methodology can rectify this conundrum.

Faced with similar hurdles while implementing OBJLoader2.

  1. As a last resort, experimentations encompassed integrating the Three examples’ obj and mtl loaders by referencing them directly within three.js:
    export { OBJLoader } from '../examples/js/loaders/OBJLoader.js'
    leading to analogous 'not a constructor' setback`

Answer №1

Joining the party a bit late, but there's a clever workaround to avoid using alternative three.js loader npm packages. You can achieve this by utilizing the imports loader in conjunction with webpack.

// It seems unnecessary to declare this as `const`, but I haven't confirmed
const THREE = require('three');

import {
  OBJLoader,
  MTLLoader
} from 'three';

require('imports-loader?THREE=three!three/examples/js/loaders/OBJLoader.js');
require('imports-loader?THREE=three!three/examples/js/loaders/MTLLoader.js');

The idea behind this approach is to use import for TypeScript compatibility, while explicitly require the loaders so that we can provide them with the necessary global THREE object. In case you encounter a dependency that requires multiple imports, like FBXLoader, you can list them separated by commas before the !path-to-file.js.

Although it may seem unconventional, this method allows us to work without depending on custom packages that may not align with your current version of three.js. I have successfully implemented this technique with both MTLLoader and OBJLoader in a React application developed with TypeScript 2.9.2.

Answer №2

Below is the package and code I used to implement the loaders:

npm install -D @types/three
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
...
const mtlLoader = new MTLLoader();
mtlLoader.load('example.mtl', (mtl) => {
  const objLoader = new OBJLoader();
  objLoader.setMaterials(mtl);
  objLoader.load('example.obj', (obj) => {
      scene.add(obj);
  };
});

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

Encountering an issue when trying to upload a photo from Angular 8 to Laravel: receiving a "Call to a member function extension() on null" error

In my project using Angular 8 for the front end and Laravel 5.8 for the backend, I encountered an issue with uploading photos. I found guidance in this tutorial from ACADE MIND. Here is my template code : <input *ngIf="photoEdit" enctype="multipart/ ...

What is the process of declaring a variable within a class in TypeScript?

When setting up an instance variable inside my Angular component like this: @Component({ selector: 'app-root', templateUrl: './app.component.html', //template: `` styleUrls: ['./app.component.css'] }) export class AppCo ...

Error: Tried to modify a property that is read-only while using the useRef() hook in React Native with Typescript

I'm facing an issue while attempting to utilize a useRef hook for a scrollview and pan gesture handler to share a common ref. Upon initializing the useRef() hook and passing it to both components, I encounter an error that states: TypeError: Attempte ...

Navigating through different components within a single page

Each segment of my webpage is a distinct component, arranged consecutively while scrolling e.g.: <sectionA></sectionA> <sectionB></sectionB> <sectionC></sectionC> All the examples I've come across involve creating ...

Trigger an Angular2 component function from an HTML element by simply clicking a button

I'm just starting out with TypeScript and Angular2 and encountering an issue when trying to call a component function by clicking on an HTML button. When I use the **onclick="locateHotelOnMap()"** attribute on the HTML button element, I receive this ...

The camera steadily advances in WebVR Cardboard using three.js technology, never stopping its forward movement

I've been experimenting with trying to create a smooth, continuous forward movement for the camera in a three.js/WebVR project, specifically with only a cardboard viewer needed. After much trial and error, I've discovered that the usual camera m ...

Scoped variable in Typescript producing a generated Javascript file

I'm currently learning TypeScript through an online course, and I've encountered a problem that seems to be related to a VSCode setting. Whenever I compile app.ts, it generates the app.js file, but I immediately encounter a TypeScript error. It& ...

Understanding how to extract an enum from a string and its corresponding value in TypeScript

I am working with a simple enum called errorCode, shown below: export enum SomeErrorCodes { none = 0, notFound = 1, duplicated = 2 } Currently, I am receiving the name of the enum as a string "SomeErrorCodes" and a number, for example, 1. How ...

What is the reason behind the ability to assign any single parameter function to the type `(val: never) => void` in TypeScript?

Take a look at the code snippet below interface Fn { (val: never): void } const fn1: Fn = () => {} const fn2: Fn = (val: number) => {} const fn3: Fn = (val: { canBeAnyThing: string }) => {} Despite the lack of errors, I find it puzzling. For ...

Leveraging Angular Observables for seamless data sharing across components

As I embark on developing my very first Angular app, I have encountered a challenge with filtering a list of book objects based on their gender attribute. The issue lies in sharing data between components – specifically the filteredData variable and the ...

updating rows in a table

Currently, I have a grid array filled with default data retrieved from the database. This data is then displayed on the front end in a table/grid format allowing users to add and delete rows. When a row is added, I only want to insert an empty object. The ...

What is the best way to conduct tests on Typescript modules that are not intended for

Even though the compiler accepts my current solution without any errors, the tests are still failing with the message "ReferenceError: myFunction is not defined". I am interested in testing the functionality of the following module using TypeScript: File1 ...

Leverage the exported data from Highcharts Editor to create a fresh React chart

I am currently working on implementing the following workflow Create a chart using the Highcharts Editor tool Export the JSON object from the Editor that represents the chart Utilize the exported JSON to render a new chart After creating a chart through ...

The Jest worker has run into 4 child process errors, surpassing the maximum retry threshold

I am a newcomer to Vue and Jest testing, and I keep encountering this error when running a specific test. While I understand that this is a common issue, I am struggling to pinpoint the exact cause of the problem. Here is the error message: Test suite fa ...

Learn how to implement icons within Textfield components using Material-UI and TypeScript in React

I have successfully created a form with validation using TypeScript Material UI and Formik. Now, I am looking to enhance the visual appeal by adding a material UI Icon within the textfield area. Below is a snippet of my code: import React from 'reac ...

Object data is not being received by the defaultValue in React Hook Form

I am currently utilizing React Hook Form to facilitate the process of editing/updating data. I retrieve my data from zustand with a value type of any, and then proceed to save it as the defaultValue in React Hook Form. However, when attempting to acquire v ...

What exactly does "tsc" stand for when I compile TypeScript using the command "(tsc greeter.ts)"?

What does tsc stand for when compiling TypeScript code? (tsc greeter.ts) tsc I'm curious about the meaning of tsc in this context. ...

Discover how to access JSON data using a string key in Angular 2

Trying to loop through JSON data in angular2 can be straightforward when the data is structured like this: {fileName: "XYZ"} You can simply use let data of datas to iterate over it. But things get tricky when your JSON data keys are in string format, li ...

What is preventing me from utilizing a union type in conjunction with redux connect?

Below is a brief example of the code I am working on: import { connect } from "react-redux"; interface ErrorProps { error: true; description: string; } interface NoErrorProps { error: false; } type TestProps = ErrorProps | NoErrorProps; ...

What is the best way to extract values from case-sensitive query param variables?

I am dealing with a URL that contains the query string id. However, the variable id can appear as either 'id' or 'Id' in the URL. From my understanding, these two variations will be treated differently. To handle URLs like the followin ...