firtoz / react-three-renderer

Render into a three.js canvas using React.
https://toxicfork.github.com/react-three-renderer-example/
MIT License
1.49k stars 155 forks source link

How to load an object (.obj) with r3r? #186

Closed shlomizadok closed 7 years ago

shlomizadok commented 7 years ago

Thanks for this awesome implementation of three.js and React 😘 !

I am struggling to load an external .obj object and use it within my React + three app.

Currently I am trying:

import React from 'react';
import ReactDOM from 'react-dom';
import React3 from 'react-three-renderer';
import TrackballControls from './TrackballControls';
import * as THREE from 'three';
import * as OBJLoader from 'three-obj-loader';
OBJLoader(THREE);

class MyClass extends React.Component {
...
  render() {
    ...
    const objLoader = new THREE.OBJLoader();
  }
}

However, I keep on getting: "export 'OBJLoader' (imported as 'THREE') was not found in 'three'

Is there any other way to load a .obj file and use it?

Thanks !

shlomizadok commented 7 years ago

Found a workaround (weird though):

import React from 'react';
import ReactDOM from 'react-dom';
import React3 from 'react-three-renderer';
import TrackballControls from './TrackballControls';
import * as THREE from 'three';
import * as OBJLoader from 'three-obj-loader';
OBJLoader(THREE);

class MyClass extends React.Component {
...
  componentDidMount() {
    ...
    this.THREE = THREE;
    const objLoader = new this.THREE.OBJLoader();
    objLoader.load(url, (object) => {...});
  }
}
andyram08 commented 6 years ago

@shlomizadok i'm trying in the same approach but im unable to load the .obj and .mtl files into the scene, can you share your example ?

toxicFork commented 6 years ago

Hi @andyram08 , what sort of issues are you running into, which method specifically are you attempting? We can try to resolve it from your end and that may help to produce a guide for the others in the future :)

andyram08 commented 6 years ago

Hi @toxicFork I'm trying to load .obj and .mtl through react-three-renderer but i'm missing out on loading the model. Currently i'm able to render a cube inside the div. However, i want to replace the cube with my .obj model.

installation:

npm install --save react@15.6.1 react-dom@15.6.1 three@0.86.0
npm install --save react-three-renderer
npm install --save three-obj-loader
npm install --save three-mtl-loader

usage: cube inside a div

import React from 'react';
import React3 from 'react-three-renderer';
import * as THREE from 'three';
import OBJLoader from 'three-obj-loader';// added while importing character .obj
import OBJLoader from 'three-mtl-loader';// added while importing character .mtl

class Simple extends React.Component {
  static propTypes = {
    width: React.PropTypes.number.isRequired,
    height: React.PropTypes.number.isRequired,
  };

  constructor(props, context) {
    super(props, context);

    this.cameraPosition = new THREE.Vector3(0, 0, 5);

    // construct the position vector here, because if we use 'new' within render,
    // React will think that things have changed when they have not.

    this.state = {
      cubeRotation: new THREE.Euler(),
    };

    this._onAnimate = () => {
      // we will get this callback every frame

      // pretend cubeRotation is immutable.
      // this helps with updates and pure rendering.
      // React will be sure that the rotation has now updated.
      this.setState({
        cubeRotation: new THREE.Euler(
          this.state.cubeRotation.x + 0.1,
          this.state.cubeRotation.y + 0.1,
          0
        ),
      });
    };
  }

  render() {
    const {
      width,
      height,
    } = this.props;

    // or you can use:
    // width = window.innerWidth
    // height = window.innerHeight

    return (<React3
      mainCamera="camera" // this points to the perspectiveCamera below
      width={width}
      height={height}

      onAnimate={this._onAnimate}
    >
      <scene>
        <perspectiveCamera
          name="camera"
          fov={75}
          aspect={width / height}
          near={0.1}
          far={1000}

          position={this.cameraPosition}
        />
        <mesh
          rotation={this.state.cubeRotation}
        >
          <boxGeometry
            width={1}
            height={1}
            depth={1}
          />
          <meshBasicMaterial
            color={0x00ff00}
          />
        </mesh>
      </scene>
    </React3>);
  }
}

export default Simple; Expected 3D model .obj .mtl but where to add this code ?


const mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl(PATH);
mtlLoader.setPath(PATH); // One of these might not be needed
mtlLoader.crossOrigin = '*'; // Use as needed
mtlLoader.load(MTL_FILE, materials => {
    materials.preload();
    // OBJ Loader
    const objLoader = new THREE.OBJLoader();
    objLoader.setMaterials(materials);
    objLoader.setPath(PATH);
    objLoader.load(OBJ_FILE, object => {
        for(let child of object.children) {
            child.material.side = THREE.DoubleSide
        }

    }, onProgress, onError);
});
shlomizadok commented 6 years ago

Hey, Sorry for the late response. I have open sourced a POC I have created a while back. Not sure it is the perfect demo, yet it is a start 😄
Please take a look at: https://github.com/shlomizadok/shalosh I'd love if the POC will turn into a demo of how to use React, Three & react-three-renderer

Hope it helps.