Three js not rendering objects in scene after OOP implementation in react

有些话、适合烂在心里 提交于 2020-01-02 20:59:11

问题


After making a stand alone three js app I wanted to make this three js app a component in my React application.

I needed multiple scenes overlayed so I made a threeApp function that instantiates a scene, camera, renderer and adds it to the DOM. So I tried to make a lot of stuff reusable.

After following this answer I managed to get some a three js scene with a spinning cube in my react app. Success! Since I already made a functioning OOP (?) implementation without react so I dove right in.

Right now I have a rendered canvas in my app but the objects in it are not getting rendered. However I can see the scene in three js inspector extension. If I console log at the animate/update functions they all fire.

This is the react component copied from this SO answer which originally worked.

import React, { Component } from 'react'
import * as THREE from 'three'

import testCube from "./viz/testCube"
import VizHandler from './VizHandler'


class Visualizer extends Component {
  constructor(props) {
    super(props)

    this.start = this.start.bind(this)
    this.stop = this.stop.bind(this)
    this.animate = this.animate.bind(this)
  }

  componentDidMount() {
    const vizHandler = this.vizHandler = new VizHandler();
    vizHandler.init(this.mount);
    this.start()
  }

  componentWillUnmount() {
    this.stop()
    // this.mount.removeChild(threeApps['vizholder'].getRenderer().domElement)
    // vizHandler.unmount(this.mount);
  }

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

  stop() {
    cancelAnimationFrame(this.frameId)
  }

  animate() {
    this.vizHandler.update(); // update / animate stuff in here

    this.vizHandler.render()
    this.frameId = window.requestAnimationFrame(this.animate)
  }

  render() {
    return (
      <div
        // style={{ width: '400px', height: '400px' }}
        ref={(mount) => { this.mount = mount }}
      />
    )
  }
}

export default Visualizer

I handle multiple threejs scenes/canvases here in the VizHandler function/class

import * as THREE from "three";
import threeApp from "./threeApp";
import WhiteRing from "./viz/WhiteRing";
import testCube from "./viz/testCube";
import Bars from "./viz/Bars";


const VizHandler = function () {

  var threeApps = [];
  var rings = new WhiteRing();
  var bars = new Bars();
  var cube = new testCube();

  function init(mount) {


      threeApps['vizholder'] = new threeApp();
      // threeApps['overlay'] = new threeApp();
      threeApps['vizholder'].init(mount, 'VizHolder') ;
      // threeApps['overlay'].init(mount, 'Overlay');

      window.scene = threeApps['vizholder'].getScene();
      window.THREE = THREE;

      const vizHolder = threeApps['vizholder'].getVizHolder();
      rings.init( vizHolder );
      bars.init( vizHolder );
      cube.init( vizHolder );

  }

  function update() {
    rings.update();
    bars.update();
    cube.update();
  }

  function render() {
    threeApps["vizholder"].render();
  }


  return {
      init: init,
      update: update,
      render: render,
      getVizHolder: function( name ) {
          if ( name ) return threeApps[name].getVizHolder();
          else return threeApps['vizholder'].getVizHolder();
      },
      getRenderer: function( name ) {
          if ( name ) return threeApps[name].getRenderer();
          else return threeApps['vizholder'].getRenderer();
      },
      getThreeApps: function() {
          return threeApps
      },
  };

};

And this is the most basic cube to that I'm trying to render.

import * as THREE from 'three';

const testCube = function () {

  let cube;

  function init (vizHolder) {

      const groupHolder = new THREE.Object3D();
      groupHolder.name = "TemplateViz";
      vizHolder.add(groupHolder);

      const geometry = new THREE.BoxGeometry(1, 1, 1)
      const material = new THREE.MeshBasicMaterial({ color: '#ffffff' })
      cube = new THREE.Mesh(geometry, material)
      cube.name = "TESTCUBE";
      groupHolder.add(cube);
      vizHolder.add(groupHolder);

  }

  function update() {
    cube.rotation.x += 0.01
    cube.rotation.y += 0.01
  }

  return {
    init: init,
    update: update,
  }

};

export default testCube;

And the result of all this is a renderer element in the dom that does not render my elements to the scene. I can change the renderer color and update the objects in the scene but I cannot make them appear.

EDIT: After solving the problem in my more simplified answer here, I forgot to post 1 important file where the error eventually occurred. The threeApp class where I make scenes, renderers and camera's. The code below was the non working code.

import * as THREE from "three";

function threeApp() {

  let camera, scene, renderer;
  let groundLight, skyLight, hemiLight;
  let vizHolder;
  let objName;
  let renderColor = '#909009';

  function init(mount, name) {

      objName = name;
      this.holderName = name;

      renderer = new THREE.WebGLRenderer({
          // antialias: true,
          // alpha: true
      });
      renderer.setSize(800, 600);

      renderer.domElement.className = "renderer";
      mount.appendChild(renderer.domElement);

      //3D SCENE
      camera = new THREE.PerspectiveCamera(70, 800 / 600, 1, 3000);
      camera.position.z = 1000;
      camera.name = "camera";


      scene = new THREE.Scene();
      // window.THREE = THREE;
      scene.name = name + " scene";
      console.log( 'name', name );
      if ( name == "VizHolder") {
          window.scene = scene;
      }
      camera.lookAt(scene);
      scene.fog = new THREE.Fog(0xffd8e5, 1000, 3000);
      scene.add(camera);

      //INIT VIZ
      vizHolder = new THREE.Object3D();
      vizHolder.name = name;

      scene.add(vizHolder);
  }


  function update () {
        render();
  }

  function render() {
    renderer.render(scene, camera);
  }

  function onResize () {

      var renderW = window.innerWidth;
      var renderH = window.innerHeight;
      camera.aspect = renderW / renderH;
      camera.updateProjectionMatrix();
      renderer.setSize(renderW, renderH);
  }

  return {
    init: init,
    render: render,
    onResize: onResize,
    getVizHolder: function() {
        return vizHolder;
    },
    getCamera: function() {
        return camera;
    },
    getScene: function() {
        return scene;
    },
    getRenderer: function() {
        return renderer;
    },
    setRenderColor: setRenderColor
}

};

export default threeApp

来源:https://stackoverflow.com/questions/48217565/three-js-not-rendering-objects-in-scene-after-oop-implementation-in-react

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!