Skip to content
This repository has been archived by the owner on Jul 20, 2020. It is now read-only.

Why react-three-renderer ? #229

Open
yiakwy opened this issue May 7, 2018 · 5 comments
Open

Why react-three-renderer ? #229

yiakwy opened this issue May 7, 2018 · 5 comments

Comments

@yiakwy
Copy link

yiakwy commented May 7, 2018

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.

@MaartenBreeedveld
Copy link

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,

@yiakwy
Copy link
Author

yiakwy commented May 8, 2018

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.

@MaartenBreeedveld
Copy link

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!

@johnrees
Copy link
Contributor

johnrees commented May 9, 2018

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.

@yiakwy
Copy link
Author

yiakwy commented May 12, 2018

@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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants