react-three-renderer
react-three-renderer copied to clipboard
Simpler React Configuration
I am struggling to integrate a fairly complex model generator into react using react three renderer. While I am well versed in Three, I am slightly daunted by the myriad of configuration issues having to do with es5 v es 6, babel, webpack shims react itself and many other configuration "opportunities".
The example you have is an integrated multi page system that is not easily decomposable and uses fairly complex babel/webpack integration.
A single or set of individual examples that do not link together that show how to do the following would be helpful.
1 - How to create a three.js mesh that is composed of many vertices and therefore does not fit into any of the prefabricated geometries and render that mesh into a scene. In other words a single class that either reads in a mesh from disk or creates one on the fly that is then put into a render function with the geometry and passed to the parent to be rendered into a canvas.
2 - A starter template that one can copy to modify and test new ideas that is not so bound up in other examples that it breaks the entire system when copied. (try copying the simple example and renaming it. In nearly every other package such a process would give me a new version that I could play with. In the R3 examples this gives me a big debugging challenge.)
3 - A single example that has one object that is lit properly that can be moved around in 3space using orbit controls or some other trackball type controls.
4 - An example of loading a simple JSON object from disk and rendering it into a scene.
5 - An example for accessing the scene object to add to without using JSX (which has to be the least inspiring language since xml).
I would gladly help to provide them if i can just get option 1 above up and running. So far no luck.
Hi James, thanks for the input. I have to admit the project is more for "using threejs if you're good with React" and not the other way. I was looking at some other starter packs but they still look like "threejs for react experts". I will keep an eye on this issue when coming up with more examples, all of them should be possible to make. Adding the "help wanted" tag for existing users to contribute!
As I said I am willing to help put together the examples as soon as I have a clean path through the code. Here are some helpful (hopefully! )suggestions based upon my work so far :)
Simplifying the build environment would help. There are some parts of the code that I know are called but only intermittently am I able to capture them in the Chrome debugger. This could be a timing issue or a render path issue, hard to tell but it is nondeterministic.
Also the stats on the page hidden in a index.html write is a bit of a finesse (said politely) . Perhaps in one example it is useful but the rest of the time it just muddles up the code.
Since I wrote this last comment I was able to put together a very clean react-three (not react three renderer) mesh instantiation. It makes a very simple class via React.createClass that is able to be rendered by this rather long line below ( without JSX).
ROBJ3 = ReactTHREE.Object3D,
RMESH = ReactTHREE.Mesh,
PARMS= { geometry: this.props.loadedGeometry, material: new THREE.MeshNormalMaterial( ) }
React.createClass({
render: function(){ return React.createElement(ROBJ3 ,null, React.createElement(RMESH ,PARMS));}
});
this is react-three speak for creating a mesh with a loaded geometry and material. While is is not pretty it is still comprehensible.
The point being that there is a mechanism to instantiate a very complex mesh by putting together several functions that can take the components of a mesh and render them into a scene.
It is unclear to me how to do this very straightforward task in react-three-renderer, or if it is even possible. As far as I can tell the ONLY renderable elements are ones that have RTR and THREE resource definitions such as boxgeometry or torusgeometry.
If this is the case then RTR can be best seen as a progress in work that is not ready for serious graphics.
If you help me by giving me the code for doing the above in R3R I would gladly do much of the other work to get some working examples that are decoupled from the existing example environment. (There is a third party example online that supposedly does this but it does not work with exiting node/npm configurations and even if it did there are some glaring errors that lead me to believe that the project was abandoned.)
I really want to use R3R and it has been useful for digging into react as a software environment but so far it appears that the basics need to be flushed out. React might be great at some things but whoever decided that HTML, XML, or JSX or for that matter any language with <> is a good language clearly has missed the JSON revolution (or is more concerned about job security then simplicity and elegance).
@jamesphilipreilly, have you seen these resources? They helped me when I was first starting out with R3R
https://tweedegolf.nl/2016/02/16/react-threejs https://github.com/tweedegolf/parsed-model https://github.com/tweedegolf/parsed_model_examples
JSX can take a bit of getting used to, and I'm still not fully onboard with how it's used in some cases, but imho the way you render a scene in R3R is profoundly elegant and simple. Maybe it will click if/when you do more with it.
I did try that example and it had configuration issues relating to recent versions of several NPM libs that now generate errors so i tried to extract the code and reuse but no cigar so far.
I hope you are right about r3r. That being said if the rendering of meshes is simple and elegant as you say (which I also hope is true) then a bit of pseudo code such as what i did for r3 above would be very helpful. Any volunteers?
I will even make it a simpler problem. The following is the simple example with no rotation or state data. How can it be modified to include a custom mesh in a separate class?
import React from 'react';
import React3 from 'react-three-renderer';
import * as THREE from 'three';
class Simple extends React.Component {
static propTypes = {
width: React.PropTypes.number.isRequired,
height: React.PropTypes.number.isRequired,
};
constructor(props, context) {
super(props, context);
}
render() {
const { width, height, } = this.props;
return
(
<React3 mainCamera="camera" width={width} height={height}>
<scene>
<perspectiveCamera name="camera" fov={75} aspect={16/9} near={0.1} far={1000} position={new THREE.Vector3(0,0,5)}/>
<mesh>
<boxGeometry width={1} height={1} depth={1}/>
<meshBasicMaterial color={0x00ff00}/>
</mesh>
</scene>
</React3>
);
}
}
export default Simple;
specifically I want to replace
<mesh>
<boxGeometrywidth={1}height={1}depth={1}/>
<meshBasicMaterialcolor={0x00ff00}/>
</mesh>
with
<MYCLASS/ >
where MYCLASS includes mesh, geometry faces and other salient info ... and given a mesh with geometry etc what is the minimal code look like to create this component?
Here is my best guess
class MYCLASS extends React.Component {
static propTypes = {
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
};
constructor(props, context) {
super(props, context);
};
render () {
return
React.createElement('mesh',{ key: loadedMesh_.uuid },' ',
React.createElement('geometry', { vertices: loadedMesh_.geometry.vertices, faces: loadedMesh_.geometry.faces }),' ',
React.createElement('MeshNormalMaterial',null),' ');
}
}
export default MYCLASS;
I played experimental software developer and was able to construct a minimal configuration for rendering into a and R3R scene. It is the following
import React from 'react';
import ReactDOM from 'react-dom';
import * as THREE from 'three';
import React3 from 'react-three-renderer';
import TrackballControls from '../../ref/trackball';
import jsonmesh from './downloader.js';
import jsonmodel from './jsonmodel.json';
class CompleteMesh extends React.Component {
static propTypes = {
width: React.PropTypes.number.isRequired,
height: React.PropTypes.number.isRequired,
};
constructor(props, context) {
super(props, context);
this.MESH = jsonmesh .getInstance(); // grab the mesh
}
componentDidMount() {
const controls = new TrackballControls(this.refs.mainCamera, ReactDOM.findDOMNode(this.refs.react3));
this.controls = controls;
}
componentWillUnmount() {
this.controls.dispose();
delete this.controls;
}
_onAnimate = () => { this.controls.update(); };
render() {
const { width, height, } = this.props;
return (
<div>
<React3 ref="react3" width={width} height={height} onAnimate={ this._onAnimate } >
<viewport x={1} y={0} width={width} height={height} cameraName={ 'mainCamera'} />
<scene>
<perspectiveCamera ref="mainCamera" name={'mainCamera'} fov={75} aspect={16/9} near={1} far={ 3000} lookAt={new THREE.Vector3(100,100,100)} position={ new THREE.Vector3(100,100, 200)} />
<object3D >
<perspectiveCamera/>
<mesh>
<geometry vertices={ this.MESH.geometry.vertices } faces={ this.MESH.geometry.faces } />
<meshNormalMaterial />
</mesh>
</object3D>
</scene>
</React3>
</div>);
}
}
export default CompleteMesh ;
A couple of highlights.
-
I could not ever see the mesh without instantiating a viewport and two cameras and pointing the first camera ref set to the cameraName of the viewport.
-
Removing either camera is fatal and I have no understanding why both are required.
-
As it turns out a separate class for one's mesh and or one's scene are not necessary
-
The inside camera needs to be wrapped in a Object3d
-
The mesh holding the loaded geometry can be inside or outside that Object3d tag.
I wish I understood the theory behind why a viewport and two cameras are needed but at least I have a working minimal subset.
The next task is to try and glue the above to a mouse picker routine to be able to select individual custom geometries.
@jamesphilipreilly I'm headed down a similar path as you. Wondering what did you end up doing?
I gave up on R3R and use dangerouslySetInnerHTML to render an iframe with a full version of three.js. The real issue is that react rendering is nondeterministic (from a three.js perspective). Many useful technologies take the same approach, for example react-based markdown and any serious svg components as well as any video rendering that i am aware of use dangerouslySetInnerHTML .
React is a useful tool and react/router somewhat useful and even less so is redux/redux-forms. Imho they are the rubik's cube for react (easy at the start but over time ridiculously hard to debug)
Functional programming is a neat methodology but its' recursive nature makes debugging a challenge. Just like oop it should implemented with the understanding that it is only part of the solution. I cannot see how three.js and react could be made to be seamlessly compatible without destroying the beauty of elegance of Three.js as it is presently implemented.