Object in scene but not visible

The intended response from the code below is to load a 3d object into a scene based on buttons clicked by the user. The first time an object is selected, it is pulled from a server, stored into a cache, and added to the scene. If a user selects a different 3d object, it will remove the 3d object currently in the scene and load the new object. If the user clicks the same object again, it will remove the object from the scene.

I’m currently having a strange bug where if I first click an object and it loads, and then I select a different object, it will remove the first object, put the 2nd object into the scene (which I verify is in the scene put printing scene to the console) but it isn’t visible. Also, if I load an object, then remove it, then try to load the same object to the screen, it isn’t rendered to the screen.

In all cases, when I look at the objects in the scene, it says that the object is there and is visible. After it doesnt show up on the 2nd load, when I click different objects, they load and are removed from the scene appropriately.

Note: I’m new to asking for help like this so unsure how much code to post. And since I’m really not sure where the issue is. No errors are thrown when executing the code, and as stated, when I print the scene to console, it states the object is in the scene, you just can’t see it

var FBXLoader = require('three-fbx-loader');


class ModelBuilder extends Component {

state = {
    objectNames: ...
    cache: {
        ...Cached3dObjectCategories
    },
    current: {
        Current3dObjects...
    }
}

setStateHandler =(category, selection, downloadedFile, fromDownload) => {
    console.log("4");
    var prevName = this.state[category];
    //if clicking already selected object
    if(this.state[category] !== selection) {
        console.log("5");
        if(fromDownload){
            console.log("6");
            const url = window.URL.createObjectURL(downloadedFile);
            this.setState({
                ...this.state,
                [category]: selection,
                cache: {
                    ...this.state.cache,
                    [category] : {
                        ...this.state.cache[category],
                        [selection]: url
                    }
                },
                current: {
                    ...this.state.current,
                    [category]: url
                },
            }, update => {
                this.updateScene(category, selection, prevName);
            })
        } else {`enter code here`
            this.setState({
                ...this.state,
                [category]: selection,
                current: {
                    ...this.state.current,
                    [category]: this.state.cache[category][selection]
                }
            }, update => {
                this.updateScene(category,selection, prevName);
            })
        }
    } else {
        this.removeObjectFromScene(selection);
        this.setState({
            ...this.state,
            [category]: '',
            current: {
                ...this.state.current,
                [category]: null
            }
        }, update => {
            console.log(this.state);

        })
    }
}

downloadObjectFromDatabase = (category, selection) => {
    console.log("2");
    return new Promise((resolve, reject) => {
        firebase.storage().ref('/Models/' + category + '/' + selection + '.fbx')
            .getDownloadURL()
            .then(url => {
                var xhr = new XMLHttpRequest();
                xhr.responseType = 'blob';
                xhr.onload = function(event) {
                    resolve(xhr.response);
                };
                xhr.open('GET', url);
                xhr.send();
            })
            .catch(error => {
                reject(error);
            })
    });
}

isObjectInCache = (category, selection) => {
    const cacheCategory = this.state.cache[category];
    let inCache = false;

    for (var object in cacheCategory) {
        if(object === selection) {
            inCache = true;
            break;
        }
    }
    return inCache;
}

async updateSelectionHandler(category, selection, setStateHandler, updateScene) {

    const alreadyInCache = this.isObjectInCache(category, selection);

    if(!alreadyInCache){
        console.log("1");
        try {
            const downloadedFile = await this.downloadObjectFromDatabase(category, selection);
            console.log("3");
            setStateHandler(category, selection, downloadedFile, true, updateScene);

        } catch (error) {
            console.log(error);
        }
     } else {
         setStateHandler(category, selection, this.state.current[category], false, updateScene);
    }
}

constructor(props) {
 super(props)

 this.start = this.start.bind(this)
 this.stop = this.stop.bind(this)
 this.animate = this.animate.bind(this)
 this.setStateHandler = this.setStateHandler.bind(this)
 this.loadObjectFromCache = this.loadObjectFromCache.bind(this);
 }

 componentDidMount() {
   this.init();
   this.updateScene();
}

componentWillUnmount() {
 this.stop()
 this.mount.removeChild(this.renderer.domElement)
}

start = () => {
 if (!this.frameId) {
   this.frameId = requestAnimationFrame(this.animate)
 }
}

stop = () => {
 cancelAnimationFrame(this.frameId)
}

animate = () => {
 this.renderScene()
 this.frameId = window.requestAnimationFrame(this.animate)
}

renderScene = () => {
 this.renderer.render(this.scene, this.camera)
}

removeObjectFromScene = (objectName) => {
   var selectedObject = this.scene.getObjectByName(objectName);
   this.scene.remove(selectedObject);
}

loadObjectFromCache = (url) => {
   return new Promise((resolve, reject) => {
       this.loader.load(
           url,
           (object) => {
               object.traverse( function ( child ) {
                   if( child.material ) {
                       child.material = new THREE.MeshStandardMaterial( { 
      color: 0xC0C0C0 } );

                   }
                   if ( child.isMesh ) {
                       child.castShadow = true;
                       child.receiveShadow = true;
                   }
               });
               object.castShadow = true;
               resolve(object);

           },
           null,
           (error) => {
               reject(error);
           }
       )
   });
 }

 async updateScene (category, selection, prevName) {
      console.log("7");
      if(selection && this.state.current[category] !== null){
          try {
              console.log("8");
              const object = await 
   this.loadObjectFromCache(this.state.current[category]);
              object.scale.set( .02, .02, .02 );
              if(prevName !== ''){
                  this.removeObjectFromScene(prevName);
              }

              object.name = selection;

              object.position.y = -1;
              this.scene.add(object);
              console.log(this.scene);
          } catch (error) {
              console.log(error);
          }
      };
      console.log(this.state);

  }

init = () => {
  this.THREE = THREE;
  this.loader = new FBXLoader();

  const width = this.mount.clientWidth
  const height = this.mount.clientHeight
  const scene = new THREE.Scene()
  const camera = new THREE.PerspectiveCamera(
    75,
    width / height,
    0.1,
    1000
  )
  //offset view so model shifts to left side of the screen
  camera.setViewOffset(width * 1.3, height * 1.3, width * .3, height * .1, width, height );

  camera.position.z = 3


  const renderer = new THREE.WebGLRenderer({ antialias: true })

  //enable orbit controls
  const controls = new OrbitControls(camera, renderer.domElement);
  controls.enabled = true;
  controls.enablePan = false;
  controls.minDistance = 2.0;
  controls.maxDistance = 3.0;
  // How far you can orbit vertically, upper and lower limits.
  // Range is 0 to Math.PI radians.
  controls.minPolarAngle = 0; // radians
  controls.maxPolarAngle = Math.PI / 2; // radians

  //changes the size of screen when browser resized
  window.addEventListener('resize', function()
      {
          var width = window.innerWidth;
          var height = window.innerHeight;
          renderer.setSize(width, height);
          camera.aspect = width / height;
          camera.updateProjectionMatrix();
      });

  //Scene Lighting
  var ambientLight = new THREE.AmbientLight(0xFFFFFF, .2);

  var keyLight = new THREE.DirectionalLight(new THREE.Color('hsl(30, 100%, 75%)'), 1.0);
  keyLight.position.set(-100, 0, 100);

  var fillLight = new THREE.DirectionalLight(new THREE.Color('hsl(240, 100%, 75%)'), 0.75);
  fillLight.position.set(100, 0, 100);

  var backLight = new THREE.DirectionalLight(0xffffff, 1.0);
  backLight.position.set(100, 0, -100).normalize();

  scene.add(ambientLight);
  scene.add(keyLight);
  scene.add(fillLight);
  scene.add(backLight);

 //add the skybox
 var geometry = new THREE.CubeGeometry(100, 100, 100);
 var cubeMaterials = [
     new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load(px), side: THREE.DoubleSide}),
     new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load(nx), side: THREE.DoubleSide}),
     new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load(py), side: THREE.DoubleSide}),
     new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load(ny), side: THREE.DoubleSide}),
     new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load(pz), side: THREE.DoubleSide}),
     new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load(nz), side: THREE.DoubleSide}),
 ];
 var cubeMaterial = new THREE.MeshFaceMaterial(cubeMaterials);
 var cube = new THREE.Mesh(geometry, cubeMaterial);
 scene.add(cube);

 renderer.setClearColor('#000000')
 renderer.setSize(width, height)

 this.scene = scene
 this.camera = camera
 this.renderer = renderer

 this.mount.appendChild(this.renderer.domElement)
 this.start()

 return scene;

}

Formatted your code for you :wink:

1 Like