Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * This is a ghetto attempt to apply a simplified functional(ish) approach
- * to having threejs render a state object.
- *
- * A few of the main problems were:
- * 1) Immutability with a mutable scene graph isn't going to work, and will
- * likely make a mess of things.
- * 2) Geometry, meshes, etc, need to be handled economically. We can't trash
- * the scene and then recreate it on every frame. This also requires mutation
- * for permanence.
- * 3) Everything seems needlessly complicated.
- *
- * This approach proposed the following:
- * 1) The State/Store is a static representation of the important parts of the
- * scene. We'll give up some control to threejs to manage things not in the
- * state object. Essentially, we'll just track what we need.
- * 2) We'll store "smart" objects in the state that monitor their values.
- * 3) When those smart objects change we'll enqueue transformation actions
- * to a camera or scene queue. Those actions will synchronize threejs
- * when the state is updated.
- *
- * Note: Currently the state here is just a representation of what would be
- * redux, vuex, or something else. It's good enough proof of concept because
- * adding a function to the camera or scene queues is relatively trivial.
- *
- * My hope with this is to be able to extend the integrations between state
- * and three js to be really declarative.
- */
- // Setup Three JS Core components
- const c = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
- const s = new THREE.Scene();
- const r = new THREE.WebGLRenderer( { antialias: true } );
- // Setup Three JS Viewport in DOM
- r.setSize( window.innerWidth, window.innerHeight );
- document.body.appendChild( r.domElement );
- // Sample state
- const state =
- {
- camera:
- {
- position:
- {
- x: 0,
- y: 0,
- z: 3
- }
- },
- shapes:
- {
- cube : new THREE.BoxGeometry( 0.2, 0.2, 0.2 )
- },
- materials:
- {
- normal : new THREE.MeshNormalMaterial()
- },
- entities :
- [
- {
- id: 0,
- geometry: 'cube',
- material: 'normal',
- position:
- {
- x: 0,
- y: 0,
- z: 0
- }
- },
- ]
- };
- // We'll make a queue to handle things that need to happen to
- // the scene graph
- // Function Queue (like a pipe of sorts)
- // Allows unary functions to be added to a queue
- // Probably replace this with ramda? :|
- class fnQueue {
- constructor() {
- this.fns = [];
- }
- add(fn) {
- this.fns.push( fn );
- }
- get() {
- return this.fns.concat();
- }
- clear() {
- this.fns = [];
- }
- run(x) {
- const fns = this.get();
- this.clear();
- return fns.reduce((i, fn) => fn(i), x);
- }
- }
- // Camera / Scene Queues
- // These queues process enqueued unary functions
- // through a reducer.
- const cQ = new fnQueue();
- const sQ = new fnQueue();
- // Render Pass
- // Each time a frame renders it processes the camera queue and scene
- // queue, applying the appropriate mutations
- function newFrame()
- {
- requestAnimationFrame( newFrame );
- r.render(
- sQ.run(s),
- cQ.run(c)
- );
- }
- // Let's get this part started
- newFrame();
- // ----------------------------------------------------------------------------
- // EXAMPLES -------------------------------------------------------------------
- // ----------------------------------------------------------------------------
- // A function to position the camera
- const positionCamera = function(vect3)
- {
- const {x,y,z} = vect3;
- return (c) => {
- c.position.x = x;
- c.position.y = y;
- c.position.z = z;
- return c;
- }
- }
- // Add camera positioning to the camera queue
- // This would be triggered by a 'set value' observer
- // of sorts on the state.
- cQ.add( positionCamera({x:0,y:0,z:2}) );
- // A function to create a mesh
- const createMesh = function(geometry, material)
- {
- return (s) => {
- s.add( new THREE.Mesh(geometry, material) );
- return s;
- }
- }
- sQ.add( createMesh( state.shapes.cube, state.materials.normal) );
Advertisement
Add Comment
Please, Sign In to add comment