{"id":1606,"date":"2017-02-09T23:29:30","date_gmt":"2017-02-10T04:29:30","guid":{"rendered":"https:\/\/rpchurchill.com\/?p=1606"},"modified":"2017-02-22T19:18:04","modified_gmt":"2017-02-23T00:18:04","slug":"webgl-incorporating-device-orientation","status":"publish","type":"post","link":"https:\/\/rpchurchill.com\/wordpress\/posts\/2017\/02\/09\/webgl-incorporating-device-orientation\/","title":{"rendered":"WebGL: Incorporating Device Orientation"},"content":{"rendered":"<p>At last night&#8217;s <a href=\"https:\/\/www.meetup.com\/DC-JavaScript\/events\/236993626\/\">DCJS<\/a> Meetup (specifically Sean&#8217;s talk referencing <a href=\"https:\/\/www.primrosevr.com\/\">this<\/a>) I learned that a means of reading the 3D orientation of a device has been readily available for some time.  <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Detecting_device_orientation\">Description<\/a>s were not hard to find.<\/p>\n<p>Setting up the listener is easy enough.  The <code>window.DeviceOrientationEvent<\/code> test will actually pass on a lot of devices, including my laptop, even if they don&#8217;t actually fire off the update events, therefore I initialize the angles to null and use them as a test for updating the camera orientation.<\/p>\n<pre class=\"toolbar-overlay:false wrap:false height-set:true lang:default decode:true \">\r\n      \/\/VR controls viewing direction\r\n      var lookAngleX;\r\n      var lookAngleY;\r\n      var lookAngleZ;\r\n      \r\n      if (!window.DeviceOrientationEvent) {\r\n        alert(\"no gyro\");\r\n      }\r\n      lookAngleX = null;\r\n      lookAngleY = null;\r\n      lookAngleZ = null;\r\n      \r\n      function handleOrientation(event) {\r\n        lookAngleX = event.beta;\r\n        lookAngleY = event.gamma;\r\n        lookAngleZ = event.alpha;\r\n      }\r\n      \r\n      window.addEventListener(\"deviceorientation\", handleOrientation);\r\n<\/pre>\n<p>If the orientation events don&#8217;t fire then I let the camera move and continue to look at the origin of the scene as before but if the events to fire I stop the camera from moving and update its orientation in space instead.  The 90 degree adjustment for rotation around the X-axis was something I added to make the view make sense.  That may be an artifact of the coordinate system I set up.  An additional adjustment may be necessary on <a href=\"https:\/\/mobiforge.com\/design-development\/html5-mobile-web-device-orientation-events\">Firefox on some devices.<\/a><\/p>\n<pre class=\"toolbar-overlay:false wrap:false height-set:true lang:default decode:true \">\r\n        \/\/update location of viewport camera\r\n        camera.position.set(x,y,z);\r\n        if (lookAngleX == null) {\r\n          camera.lookAt(global3DLookTarget);\r\n        } else {\r\n          camera.rotation.x = (lookAngleX - 90.0) * Math.PI \/ 180.0;\r\n          camera.rotation.y = lookAngleY * Math.PI \/ 180.0;\r\n          camera.rotation.z = lookAngleZ * Math.PI \/ 180.0;\r\n          cInc = 0.0;\r\n        }\r\n      }\r\n<\/pre>\n<p>Here&#8217;s a direct <a href=\"https:\/\/www.rpchurchill.com\/demo\/des\/handle_resize_20170209.html\">link<\/a> to test on your mobile device.  Let me know if it works for you.  <a href=\"https:\/\/threejs.org\/examples\/misc_controls_deviceorientation.html\">Here<\/a>&#8216;s a different way to see if your device even supports this functionality.<\/p>\n<p>This setup looks like it works on my iPhone for small rotations but it really doesn&#8217;t behave the way I&#8217;d want it to.  There&#8217;s clearly a lot <a href=\"https:\/\/github.com\/janantala\/Gyrocopter\/blob\/master\/Device%20Orientation.rst\">more going on<\/a>.  I&#8217;m going to dig into that a bit later but in the meantime I found an even more direct &#8212; and easier &#8212; way to accomplish this.  Addendum, February 22, 2017:  No, that&#8217;s not what was going on, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Quaternions_and_spatial_rotation\">this<\/a> is what was going on.  The rotations I did accounted for the directional vector but not the rotation around that vector.  This is the extra factor addressed in DeviceOrientationControls.js.<\/p>\n<p>Three.js already includes a way to incorporate a device&#8217;s orientation, and that is by including the capabilities in DeviceOrientationControls.js.  An example is <a href=\"https:\/\/github.com\/mrdoob\/three.js\/blob\/master\/examples\/css3d_panorama_deviceorientation.html\">here<\/a>.  I pulled all of the previous code out and replaced it with all of three new lines identified below, and also set the orbit increment to zero.<\/p>\n<pre class=\"toolbar-overlay:false wrap:false height-set:true lang:default decode:true \">\r\n    <script src=\"js\/three.js\"><\/script>\r\n    <script src=\"js\/Detector.js\"><\/script>\r\n    <script src=\"js\/DeviceOrientationControls.js\"><\/script>  \/\/new\r\n\r\n    ...\r\n\r\n        aspectRatio = window.innerWidth\/window.innerHeight;\r\n        camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 1000);\r\n\r\n        renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});\r\n        renderer.setSize(window.innerWidth, window.innerHeight);\r\n        \r\n        canvas = renderer.domElement;\r\n        document.body.appendChild(canvas);  \/\/can also be appended to a DIV\r\n        \r\n        controls = new THREE.DeviceOrientationControls( camera );  \/\/new\r\n\r\n        scene = new THREE.Scene();\r\n        renderer.setClearColor(\"#000000\",1);\r\n\r\n    ...\r\n\r\n      function render() {\r\n        \/\/each cube rotates around a different axis\r\n        cube1.rotation.x += 0.01;\r\n        cube2.rotation.y += 0.01;\r\n        cube3.rotation.z += 0.01;\r\n\r\n        cylRotations();\r\n\r\n        controls.update();  \/\/new\r\n\r\n        renderer.render(scene, camera);\r\n\r\n        requestAnimationFrame(render);\r\n      }\r\n<\/pre>\n<p>It could not be easier.<\/p>\n<p>My quick hack for checking this out on your device directly is <a href=\"https:\/\/www.rpchurchill.com\/demo\/des\/handle_resize_20170209a.html\">here<\/a>.  It won&#8217;t do anything on a device that doesn&#8217;t support sensing of orientation but it looks and works great on my phone.<\/p>\n<p>The next thing I&#8217;d have to do is figure out how to determine whether the device supports this new addition and revert to the previous orbit-and-look-at-the-origin behavior.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>At last night&#8217;s DCJS Meetup (specifically Sean&#8217;s talk referencing this) I learned that a means of reading the 3D orientation of a device has been readily available for some time. Descriptions were not hard to find. Setting up the listener &hellip; <a href=\"https:\/\/rpchurchill.com\/wordpress\/posts\/2017\/02\/09\/webgl-incorporating-device-orientation\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[149,49,133,134],"_links":{"self":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1606"}],"collection":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/comments?post=1606"}],"version-history":[{"count":11,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1606\/revisions"}],"predecessor-version":[{"id":1682,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/posts\/1606\/revisions\/1682"}],"wp:attachment":[{"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/media?parent=1606"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/categories?post=1606"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rpchurchill.com\/wordpress\/wp-json\/wp\/v2\/tags?post=1606"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}