react-three-renderer icon indicating copy to clipboard operation
react-three-renderer copied to clipboard

Why react-three-renderer ?

Open yiakwy opened this issue 7 years ago • 5 comments

Hello I find this when I am exploring integration with electron and three.js-editor.

I developed a project using react, mobx, mobx-react and three (es6, webpack). For me, three provides scene graph to manage three objects. And react interacts with doms.

I cannot see clearly why we need to develop react-three renderer

Here is what I have done

src/ app.js (animation routine): defines "app" to to store global objects store/states.js: defines dom-data bidirectional binding and notify RENDERERE to use new to data in udpate renderer: three renderer Singleton in es6 and export interfaces to modify inner data managed by scene graph ui/: react components, like editor, gui and so on

The only thing you need is to trigger data initialization of renderer after React component mounted

Why react-three-renderer? I am seriously.

yiakwy avatar May 07 '18 04:05 yiakwy

Hi yiakwy, I'm really curious at this. Is all going well with memory management (i.e. is the THREE script also decently unmounting)?

Would you mind posting a uber-basic working example?

Cheers,

MaartenBreeedveld avatar May 08 '18 07:05 MaartenBreeedveld

Hi @MaartenBreeedveld Here are some excerpts from my codes (I am currently writing codes for company not for myself)

var app = {

}
window.app = app

import RENDERER from "renderer/renderer"
import * as ReactDOM from "react-dom"
import Editor from "scene/editor.js"
import { Provider } from "mobx-react"
import React from "react"
import observableSceneStore from "mobx-stores/state"
import runtime from "serviceworker-webpack-plugin/lib/runtime"
import registerEvents from "serviceworker-webpack-plugin/lib/browser/registerEvents"

// initalize your dom and workers first

// dom
ReactDOM.render(<Provider store={ observableSceneStore }><Editor /></Provider>, document.getElementById("wrapper"))

function animate() {
  requrestAnimationFrame(aniamte)
  // tween, udpate control, anything else inside here
   app.update(RENDERER)
}

// Now the Dom is ok, let us run main loop and begin to  @handlel events
 animate()

Hope this helps you.

For the dom part that is easy

// scene.js

import React from "react"
import {observer, inject} from "mobx-react"

import RENDERER from "renderer/renderer"
import Viewport from "UICom/viewport"

const ca = ".canvas"

@inject("store") @observer 
export default class Scene extends React.Component {
	constructor(props) {
		super(props)
	}

	componentDidMount() {
		RENDERER.init(ca)
	}

	render() {
		return (
			<div className="scene row">
				<Viewport />
			</div>
		)
	
	}

}

I use combination of quadtree and kdtree for active memory management, If I want to find something quickly. If a block of memory is not active, I will post it to local storage using worker aysnc api. You can treat it like redis hot key.

/*
 * @author Lei, ([email protected]), asynchronous 
 */ 
let extend = function(array_) {
	Array.prototype.push.apply(this, array_)
	return this 
}
Array.prototype.extend = extend 

export function inject_scope(...dep) {
	var fn = arguments[0],
		extended_args

	console.log(`inject_scope variables: ${dep}`)
	extended_args = Array.prototype.slice.apply(arguments).slice(1, arguments.length)

	return function wrapped(...inp) {
		console.log(`wrapped func inp: ${inp}`)
		var args_ = Array.prototype.slice.apply(inp)
		args_.extend(extended_args)
		return fn.apply(null, args_)
	}

}

export function channel_msg(resolve, reject, worker, msg) {
	return new Promise(function(resolve, reject) {
		let channel = new MessageChannel()
		channel.port1.onmessage = function(evt) {
			if (evt.data.error) {
				reject(evt.data.error)
			} else {
				resolve(evt.data)
			}
		}

		worker.postMessage(msg, [channel.port2])
	}).then(resolve).catch(reject)
}

export async function send(worker, msg, resolve, reject) {
 	// let promise = new Promise(inject_scope(channel_msg, worker, msg)).then(resolve).catch(reject),
	let promise = channel_msg(resolve, reject, worker, msg),
		data 
	data = await promise
	return data 
}

I am not using high resolution shaders for rendering. THREE provides a convenient way to interact with gpu clip queue. I think it is ok for the moment.

yiakwy avatar May 08 '18 16:05 yiakwy

Hi yiakwy,

Thank you very much for this example. It does look crazy simple indeed! I'll have a go at it and try to get it working. Cheers!

MaartenBreeedveld avatar May 09 '18 08:05 MaartenBreeedveld

I can only speak as a user of the library (and I haven’t used it for quite some time- plan to again soon!), but I think that one of the headline features it provides is a declarative way to construct and manipulate the contents of a THREE.Scene.

johnrees avatar May 09 '18 09:05 johnrees

@johnrees I think the difference between us is that for me THREE.Scene is a just scene graph to manage objects and is responsible for canvas rendering. I don't think it has any relationship with dom. While Dom will use observers and signals to manage complex interaction. That is not what three is good at.

yiakwy avatar May 12 '18 07:05 yiakwy