2

I am creating a scene in three js with two models in .glb format; I am following a pre-recorded class and I have followed exactly all the steps. We create a class for the models in model.js and in index.js we define them. Everything was working fine until from model.js we created a material for the models and it only loads in one of them. I have checked everything, searched for similar answers here and I can't find the error because everything seems to be fine.

This is model.js (the class)

import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'

class Model {
    constructor(obj){
        //console.log(obj)
        this.name = obj.name
        this.file = obj.file
        this.scene = obj.scene

        this.loader = new GLTFLoader()
        this.dracoLoader = new DRACOLoader()
        this.dracoLoader.setDecoderPath('./draco/')
        this.loader.setDRACOLoader(this.dracoLoader)

        this.init()
    }

    init (){
        this.loader.load(this.file, (response) => {
           console.log(response)

            this.mesh = response.scene.children[0]
            this.material = new THREE.MeshBasicMaterial({
                color: 'blue',
                wireframe: true
            })
            this.mesh.material = this.material
            this.scene.add(this.mesh)
        })
    }
}

export default Model

And this is my index.js (the scene)

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Model from './model';

/*------------------------------
Renderer
------------------------------*/
const renderer = new THREE.WebGLRenderer({
  antialias: true,
  alpha: true
});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );


/*------------------------------
Scene & Camera
------------------------------*/
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 
  50, 
  window.innerWidth / window.innerHeight,
  0.1,
  100
);
camera.position.z = 5;
camera.position.y = 1;


/*------------------------------
Mesh
------------------------------*/
const geometry = new THREE.BoxGeometry(2, 2, 2);
const material = new THREE.MeshBasicMaterial( { 
  color: 0x00ff00,
} );
const cube = new THREE.Mesh( geometry, material );
//scene.add( cube );


/*------------------------------
OrbitControls
------------------------------*/
const controls = new OrbitControls( camera, renderer.domElement );


/*------------------------------
Helpers
------------------------------*/
const gridHelper = new THREE.GridHelper( 10, 10 );
scene.add( gridHelper );
const axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );


/*------------------------------
Models
------------------------------*/
const laptop = new Model({
  name: 'laptop',
  file: './models/laptop.glb',
  scene: scene
})

const humano = new Model({
  name: 'humano',
  file: './models/humano.glb',
  scene: scene
})


/*------------------------------
Loop
------------------------------*/
const animate = function () {
  requestAnimationFrame( animate );
  renderer.render( scene, camera );
};
animate();


/*------------------------------
Resize
------------------------------*/
function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
}
window.addEventListener( 'resize', onWindowResize, false );

And this is how it look like: The material applies to the first model, but not to the second.

I tried to have it searched throughout the index without success.

I suspect this is the error, but the truth is that I am very novice and I have no clue how or why my children element comes out empty. This is my teachers console This is my teacher's console (children element attention) And this is mine....My console, my children array is empty

genpfault
  • 51,148
  • 11
  • 85
  • 139

1 Answers1

1

I'm also a Three.js novice, but it looks like DracoLoader loads a geometry not a mesh so the way you're crafting your model might be causing the issue. Does instantiating a new THREE.Mesh with the downloaded geometry and material fix the issue:

    init (){
        this.loader.load(this.file, (response) => {
           console.log(response)

            this.geometry = response.scene.children[0];
            this.material = new THREE.MeshBasicMaterial({
                color: 'blue',
                wireframe: true
            })
            this.mesh = new THREE.Mesh( this.geometry, this.material );
            this.scene.add(this.mesh)
        })
    }
teddybeard
  • 1,964
  • 1
  • 12
  • 14
  • 1
    you were right teddybeard! At first the change to the code you proposed did not work but, you were right with the dracoloader; my model had a lot of shaders that created a group so when parsing what happened is that the geometry was nested in that group and the Dracoloader did not access it. I tried with another model I had and it worked fine! Thank you very much for your help! – AlMustieles Apr 04 '22 at 21:50