Guest User

ThreeJS updated by Queue System

a guest
Aug 30th, 2019
689
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * This is a ghetto attempt to apply a simplified functional(ish) approach
  3.  * to having threejs render a state object.
  4.  *
  5.  * A few of the main problems were:
  6.  *  1) Immutability with a mutable scene graph isn't going to work, and will
  7.  *      likely make a mess of things.
  8.  *  2) Geometry, meshes, etc, need to be handled economically. We can't trash
  9.  *      the scene and then recreate it on every frame. This also requires mutation
  10.  *      for permanence.
  11.  *  3) Everything seems needlessly complicated.
  12.  *
  13.  * This approach proposed the following:
  14.  *  1) The State/Store is a static representation of the important parts of the  
  15.  *      scene. We'll give up some control to threejs to manage things not in the
  16.  *      state object. Essentially, we'll just track what we need.
  17.  *  2) We'll store "smart" objects in the state that monitor their values.
  18.  *  3) When those smart objects change we'll enqueue transformation actions
  19.  *      to a camera or scene queue. Those actions will synchronize threejs
  20.  *      when the state is updated.
  21.  *
  22.  *  Note: Currently the state here is just a representation of what would be
  23.  *  redux, vuex, or something else. It's good enough proof of concept because
  24.  *  adding a function to the camera or scene queues is relatively trivial.
  25.  *
  26.  *  My hope with this is to be able to extend the integrations between state
  27.  *  and three js to be really declarative.
  28.  */
  29.  
  30. // Setup Three JS Core components
  31. const c  = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
  32. const s  = new THREE.Scene();
  33. const r  = new THREE.WebGLRenderer( { antialias: true } );
  34.  
  35. // Setup Three JS Viewport in DOM
  36. r.setSize( window.innerWidth, window.innerHeight );
  37. document.body.appendChild( r.domElement );
  38.  
  39. // Sample state
  40. const state =
  41. {
  42.     camera:
  43.     {
  44.         position:
  45.         {
  46.             x: 0,
  47.             y: 0,
  48.             z: 3
  49.         }
  50.     },
  51.     shapes:
  52.     {
  53.         cube : new THREE.BoxGeometry( 0.2, 0.2, 0.2 )
  54.     },
  55.     materials:
  56.     {
  57.         normal : new THREE.MeshNormalMaterial()
  58.     },
  59.     entities :
  60.     [
  61.         {
  62.             id: 0,
  63.             geometry: 'cube',
  64.             material: 'normal',
  65.             position:
  66.             {
  67.                 x: 0,
  68.                 y: 0,
  69.                 z: 0
  70.             }
  71.         },
  72.     ]
  73. };
  74.  
  75.  
  76. // We'll make a queue to handle things that need to happen to
  77. // the scene graph
  78.  
  79. // Function Queue (like a pipe of sorts)
  80. // Allows unary functions to be added to a queue
  81. // Probably replace this with ramda? :|
  82. class fnQueue {
  83.     constructor() {
  84.         this.fns = [];
  85.     }
  86.     add(fn) {
  87.         this.fns.push( fn );
  88.     }
  89.     get() {
  90.         return this.fns.concat();
  91.     }
  92.     clear() {
  93.         this.fns = [];
  94.     }
  95.     run(x) {
  96.         const fns = this.get();
  97.         this.clear();
  98.         return fns.reduce((i, fn) => fn(i), x);
  99.     }
  100. }
  101.  
  102. // Camera / Scene Queues
  103. // These queues process enqueued unary functions
  104. // through a reducer.
  105. const cQ = new fnQueue();
  106. const sQ = new fnQueue();
  107.  
  108. // Render Pass
  109. // Each time a frame renders it processes the camera queue and scene
  110. // queue, applying the appropriate mutations
  111. function newFrame()
  112. {  
  113.     requestAnimationFrame( newFrame );
  114.     r.render(
  115.         sQ.run(s),
  116.         cQ.run(c)
  117.     );
  118. }
  119.  
  120. // Let's get this part started
  121. newFrame();
  122.  
  123.  
  124. // ----------------------------------------------------------------------------
  125. // EXAMPLES -------------------------------------------------------------------
  126. // ----------------------------------------------------------------------------
  127.  
  128. // A function to position the camera
  129. const positionCamera = function(vect3)
  130. {
  131.     const {x,y,z} = vect3;
  132.     return (c) => {
  133.         c.position.x = x;
  134.         c.position.y = y;
  135.         c.position.z = z;
  136.         return c;    
  137.     }
  138. }
  139.  
  140. // Add camera positioning to the camera queue
  141. // This would be triggered by a 'set value' observer
  142. // of sorts on the state.
  143. cQ.add( positionCamera({x:0,y:0,z:2}) );
  144.  
  145.  
  146. // A function to create a mesh
  147. const createMesh = function(geometry, material)
  148. {
  149.     return (s) => {
  150.         s.add( new THREE.Mesh(geometry, material) );
  151.         return s;
  152.     }
  153. }
  154.  
  155. sQ.add( createMesh( state.shapes.cube, state.materials.normal) );
Advertisement
Add Comment
Please, Sign In to add comment