block by micahstubbs 94e06c2849b6c7c60105d0243bc1936a

aframe-blocks roomscale 03 - bigger blocks

Full Screen

the camera position is currently a bit off in the Vive. checkout this commit commit hash 48e99fbb1bc66bd4b890d8bb170287d61092109e for a version where the camera position tracks the Vive HMD position when in VR. follow the stackoverflow question how to reset camera position on enter VR? for a possible method to show a custom camera position in 2D mode and a glued-to-the-hmd camera position when in VR

–<>–

a roomscale VR scene targeting the HTC Vive

use the front-trigger on either Vive controller to pick up and inspect a block

block a-boxes positions are closer to the origin than in previous examples so that they are within reach from in roomscale VR. ROADMAP: teleport locomotion ;-)

many thanks to @bryik_ws, @utopiah, @donrmccurdy over at the A-Frame slack for help getting the interaction working.

do get a slack invite of your own and check out the other places the A-Frame community gathers


all the blocks with thumbnail images created during the 2016 #d3unconf

here we use aframe’s a-boxes, which are kind of like SVG rects

a fork of aframe + d3 + bl.ocks from @donrmccurdy

falling blocks brought to you by the aframe-physics-system, also from @donrmccurdy

inspired by the conversations at the 3d and VR 11am session in the Alcatraz Room at the 2016 d3 unconference

forked from micahstubbs‘s block: aframe-blocks roomscale 03

forked from anonymous‘s block: aframe-blocks roomscale 03 -

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>A-Frame / Bl.ocks / D3</title>
    <script src="https://rawgit.com/aframevr/aframe/master/dist/aframe-master.min.js"></script>
    <script src="https://cdn.rawgit.com/donmccurdy/aframe-physics-system/v1.2.0/dist/aframe-physics-system.min.js"></script>
    <script src="aframe-extras.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.7/d3.js"></script>
  </head>
  <body>
    <!-- normal earth gravity, normal physics mode -->
    <a-scene physics="debug: false; restitution: 0.001; friction: 0.5; gravity: -2">

      <!-- Player -->
      <a-entity id='cameraWrapper' position='1 1.8034 1' rotation='-35 30 0'>
        <a-entity camera look-controls wasd-controls="fly: true"></a-entity>
      </a-entity>

      <!-- Terrain -->
      <a-plane static-body color="#CCCCCC" height="100" width="100" rotation="-90 0 0"></a-plane>

      <!-- Lighting -->
      <a-entity light="type: point; color: #f4f4f4; intensity: 0.2; distance: 0" position="8 10 18"></a-entity>
      <a-entity light="type: point; color: #f4f4f4; intensity: 0.6; distance: 0" position="-8 10 -18"></a-entity>
      <a-entity light="type: ambient; color: #f4f4f4; intensity: 0.4;" position="-8 10 -18"></a-entity>
    </a-scene>
    <script>
      function render () {
        d3.json('blocks.json', function(blocks) {
          //
          // build a table
          //

          const table = {
            center: {
              x: 0.2,
              y: 0.75,
              z: -0.5
            },
            width: 3.6,
            height: 0.05,
            depth: 1.6,
            color: 'darkgray',
            leg: {
              width: 0.1,
              depth: 0.1
            }
          }

          // table top
          d3.select('a-scene')
            .append('a-box')
            .attr('static-body', '')
            .attr('position', `${table.center.x} ${table.center.y} ${table.center.z}`)
            .attr('width', table.width)
            .attr('height', table.height)
            .attr('depth', table.depth)
            .attr('color', table.color);

          // //stackoverflow.com/questions/5834318/are-variable-operators-possible
          // operators
          const ops = {
            '+': (a, b) => a + b,
            '-': (a, b) => a - b
          };

          legPositionSigns = [
            ['+', '-', '+', '-'],
            ['-', '+', '+', '-'],
            ['+', '-', '-', '+'],
            ['-', '+', '-', '+']
          ];

          legPositionSigns.forEach(d => {
            const x = ops[d[1]](ops[d[0]](table.center.x, (table.width / 2)), (table.leg.width / 2));
            const y = 0;
            const z = ops[d[3]](ops[d[2]](table.center.z, (table.depth / 2)), (table.leg.depth / 2));

            d3.select('a-scene')
              .append('a-box')
              .attr('static-body', '')
              .attr('position', `${x} ${y} ${z}`)
              .attr('width', table.leg.width)
              .attr('height', table.center.y * 2)
              .attr('depth', table.leg.depth)
              .attr('color', table.color);
          })

          //
          // create cards with d3 blocks on them
          // drop the cards on the table
          //s

          //
          // for each d3 example in the blocks data
          // add an a-box to the scene
          // with the thumbnail of that d3 example
          // as the image texture for that a-box
          //
          const r = 0.5;
          d3.select('a-scene')
             .append('a-entity')
               .attr('id', 'blocks')
            .selectAll('.throwable')
              .data(blocks)
              .enter()
              .append('a-box')
                .classed('block', true)
                .classed('throwable', true)
                //.attr('dynamic-body', '')
                .attr('dynamic-body', '')
                // .attr('velocity', '')
                .attr('width', 0.48)
                .attr('height', 0.25)
                .attr('depth', 0.25)
                //.attr('scale', {x: 0.48, y: 0.25, z: 0.025})
                .attr('position', (d, i) => ({
                  x: (i + 2) * 0.008,
                  y: (i / 3) + 0.075 +  table.center.y,
                  z: 0.05 - (Math.random() *2)
                }))
                .attr('rotation', "-90 0 0")
                .attr('material', (d) => {
                  const thumbnailUrl = `url(//gist.githubusercontent.com/${d.owner.login}/${d.id}/raw/${d.sha}/thumbnail.png)`;
                  // const thumbnailUrl = `url(//bl.ocks.org/${d.owner.login}/raw/${d.id}/${d.sha}/thumbnail.png)`
                  return { src: thumbnailUrl }; 
                });

          //
          // after adding all grabbable objects to the scene
          // add the Vive controllers
          //

          // add left controller 
          d3.select('a-scene')
            .append('a-entity')
              .attr('id', 'leftController')
              .attr('vive-controls', 'hand: left')
              .attr('static-body', 'shape: sphere; sphereRadius: 0.02;')
              .attr('sphere-collider', 'objects: .throwable')
              .attr('grab', '');

          // add right controller
          d3.select('a-scene')
            .append('a-entity')
              .attr('id', 'rightController')
              .attr('vive-controls', 'hand: right')
              .attr('static-body', 'shape: sphere; sphereRadius: 0.02;')
              .attr('sphere-collider', 'objects: .throwable')
              .attr('grab', '');

          //
          // if a VR display (like the Vive headset begins presenting
          // (if the scene goes into VR mode)
          // reset the camera position and rotation
          //
          window.onvrdisplaypresentchange = function() {
            const VRDisplays = Navigator.getVRDisplays()
            const VRDisplay = VRDisplays[0];
            const pose = VRDisplay.getPose();
            console.log('VRDisplay pose', pose);
            // d3.select('#cameraWrapper')
            //   .attr('position', '0 0 0')
            //   .attr('rotation', '0 0 0');
          }
        });
      }

      var sceneEl = document.querySelector('a-scene');
      if (sceneEl.hasLoaded) {
        render();
      } else {
        sceneEl.addEventListener('loaded', render);
      }
    </script>
  </body>
</html>

aframe-vive.html

<html>
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no,user-scalable=no,maximum-scale=1">
    <title>Examples • Vive</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r81/three.min.js"></script>
    <script src="aframe.min.js"></script>
    <script src="aframe-extras.js"></script>
  </head>
  <body>
    <a-scene physics="debug: true">
      <!-- Player -->
      <a-entity camera look-controls></a-entity>
      <a-entity static-body="shape: sphere; sphereRadius: 0.02;" vive-controls="hand: left" sphere-collider="objects: .cube;" grab></a-entity>
      <a-entity static-body="shape: sphere; sphereRadius: 0.02;" vive-controls="hand: right" sphere-collider="objects: .cube;" grab></a-entity>

      <a-box class="cube" dynamic-body position="0 0.25 -1" width="0.5" height="0.5" depth="0.5" color="red"></a-box>
      <a-box class="cube" dynamic-body position="-1 0.25 -1" width="0.5" height="0.5" depth="0.5" color="green"></a-box>
      <a-box class="cube" dynamic-body position="1 0.25 -1" width="0.5" height="0.5" depth="0.5" color="blue"></a-box>

      <!-- Terrain -->
      <a-grid static-body></a-grid>

      <!-- Lighting -->
      <a-entity light="type: point; color: #f4f4f4; intensity: 0.2; distance: 0" position="8 10 18"></a-entity>
      <a-entity light="type: point; color: #f4f4f4; intensity: 0.6; distance: 0" position="-8 10 -18"></a-entity>
      <a-entity light="type: ambient; color: #f4f4f4; intensity: 0.4;" position="-8 10 -18"></a-entity>
    </a-scene>
  </body>
</html>

blocks.json

[  
  {  
    "id":"3757fe53ea94da4100db2e5071ea8289",
    "sha":"f37923e838ee6db8fcb20091d305ebce04404f1b",
    "description":"d3 blocks on a-boxes",
    "owner":{  
      "login":"micahstubbs"
    }
  },
  {  
    "id":"e70e14483fe01eb0a3ea7d1d46a30571",
    "sha":"7e3906f8d8a9e5d79d61f2b77cc16f2829cb4a92",
    "description":"Musical Hexagons",
    "owner":{  
      "login":"vasturiano"
    }
  },
  {  
    "id":"0ba5ee8bd3773d70462523679d4ef5a4",
    "sha":"30d1ebaccc65e061989090e948526917c09db5f7",
    "description":"Delaunay Force Mesh II",
    "owner":{  
      "login":"erlenstar"
    }
  },
  {  
    "id":"de2b023d968abb7276b894409efdac56",
    "sha":"2a168d34c566b37bbdacbeb144c8ff9e14a32175",
    "description":"merging selections",
    "owner":{  
      "login":"enjalot"
    }
  },
  {  
    "id":"7d3f8beb9faa183fc8d4fe3fd1610e00",
    "sha":"b92274a2b8d9e8653ca020d89bc42e75c086bf09",
    "description":"d3 yoga",
    "owner":{  
      "login":"enjalot"
    }
  },
  {  
    "id":"57fbb830ba7e62caa46a82891168bc29",
    "sha":"a5ae874d673654d9fc7a18e09efca0591082b8bb",
    "description":"CMYK zoom",
    "owner":{  
      "login":"veltman"
    }
  },
  {  
    "id":"e8ccca52559796be775553b467593a9f",
    "sha":"269b11fe342729ca6a70db087ff0e3f2fd8b2122",
    "description":"Continuous Legend",
    "owner":{  
      "login":"syntagmatic"
    }
  },
  {  
    "id":"6c73711f8f24af9808a9031a69f75b18",
    "sha":"52e696e66b5bb8d833b82ea5b429532a4336f96f",
    "description":"Stereographic",
    "owner":{  
      "login":"erlenstar"
    }
  },
  {  
    "id":"a1eb3bdecd2ab1be1de2425a260cc0f7",
    "sha":"feca193fc32e1606b0e53a9a873c797f2e332b64",
    "description":"Spirograph Geometric Flowers",
    "owner":{  
      "login":"EfratVil"
    }
  },
  {  
    "id":"8c5a0e697673fd676be6823589e1ce31",
    "sha":"40dcc4e31ed53cb403e36dd07288678f21ae6cfe",
    "description":"stroke-dash-array",
    "owner":{  
      "login":"jermspeaks"
    }
  },
  {  
    "id":"b04d673fbfc665f2c98f382e2c79a9ad",
    "sha":"6e7cf7e122c99bfa6bfa47e6f035472020e9730a",
    "description":"Voronoi Tessellation",
    "owner":{  
      "login":"git-ashish"
    }
  },
  {  
    "id":"1fd92b8c309a0fdc71b0a64c788a70e7",
    "sha":"227f453f79e7f56e2c4cbec1dc0110bfe5960e18",
    "description":"Canvas Voronoi",
    "owner":{  
      "login":"git-ashish"
    }
  },
  {  
    "id":"6a6c2f11f9493adba658003a5a18a107",
    "sha":"d7c669281c38b23d8b21eecb56ed6991e6d2c10b",
    "description":"Voronoi Labels",
    "owner":{  
      "login":"git-ashish"
    }
  },
  {  
    "id":"a5d147cd45c624e8811238f0a5480439",
    "sha":"7341de0028d33120fa8316619b8d0e6fdb170410",
    "description":"Comunidad Valenciana population(d3v4)",
    "owner":{  
      "login":"LuisSevillano"
    }
  },
  {  
    "id":"cd0c38a20141e997e926592264067db3",
    "sha":"5766833b6df73d777c7b6f10b3fc088bf32d99b2",
    "description":"cluster force",
    "owner":{  
      "login":"ericsoco"
    }
  },
  {  
    "id":"50a350e86de82278ffb2df248499d3e2",
    "sha":"137caaf4c0de8590d808ee35bf2ab6668109374c",
    "description":"CMYK halftone printing",
    "owner":{  
      "login":"veltman"
    }
  },
  {  
    "id":"32f369bb437d7c23198b9b9ccc8d4751",
    "sha":"c7f2be04e7fe9a4781940e73fb1896eb471714db",
    "description":"d3.unconf 2016, v11",
    "owner":{  
      "login":"micahstubbs"
    }
  },
  {  
    "id":"a7495ca3d5b322a6697530feb62fceef",
    "sha":"719e306c9885a691244c01a228aa84ca594b299a",
    "description":"Painting Manhattan-distance Voronoi",
    "owner":{  
      "login":"Fil"
    }
  },
  {  
    "id":"99767e64051096388078913afca3ff4e",
    "sha":"ac755a56347c9941c8e0d27067e69cdc41b4c0b9",
    "description":"Choropleth with d3-cluster-scale",
    "owner":{  
      "login":"schnerd"
    }
  },
  {  
    "id":"82144236b9a920f77e3af1776d265c57",
    "sha":"ff6b6f78560e73ddc3735ded012fba7524bfbc8b",
    "description":"d3.unconf 2016, v10",
    "owner":{  
      "login":"sxywu"
    }
  }
]