Neo Bui's profile

Mobile Gyroscope

     This portfolio will show how to collect gyroscope data from a iOS device by using html code to access the device.

     Reference:
      Clay Kent 2015, Mobile Gyroscope with Javascript and Quaternions Programming Tutorial Part 1, Asterix Creative LLC, retrieved 05 September 2018, <http://www.asterixcreative.com/blog/mobile-gyroscope-with-javascript-and-quaternions-programming-tutorial-part-1/>.

// This is the final html code with note to explain functions
// First let’s start with a generic page to show our data
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Gyro Demo</title>
<style>
  body
  {
    margin: 0px;
    padding: 0px;
    font-size:60px;
  }
  canvas
  {
    margin: 0px;
    width: 100%;
    height: 100% ;
    /*The following are not mandatory for canvas to work, but are there because we want the canvas to take up the whole screen while still being able to see the original text*/
    position: fixed;
    top:0px;
    z-index: -10;
  }
</style>
</head>

<body>
    alpha:<span id="alpha"></span><br>
    beta:<span id="beta"></span><br>
    gamma:<span id="gamma"></span><br>
    status:<span id="status"></span><br>
    <canvas id="myCanvas" width="1022" height="986"></canvas>
<script>

// Create deviceOrientationData to receive gyroscope data from mobile device
var deviceOrientationData ={alpha:0,beta:0,gamma:0};//init with 0 as defaults
if (window.DeviceOrientationEvent)
{
//
    window.addEventListener("deviceorientation", function ()
{//gyro
        processGyro(event.alpha, event.beta, event.gamma);
    }
, true);
}

// This Function is created to display gyroscope data to the screen, only work on phone
function processGyro(alpha,beta,gamma)
{
    deviceOrientationData.alpha=alpha;
    
    deviceOrientationData.beta=beta;
    
    deviceOrientationData.gamma=gamma;

    document.getElementById("alpha").innerHTML=alpha;
    document.getElementById("beta").innerHTML=beta;
    document.getElementById("gamma").innerHTML =gamma;

    //This is an example of using gyroscope data with if statement to print text to screen
    if (gamma >= -20 && gamma <= 20)
    {
        document.getElementById("status").innerHTML = "vibrating on";
    }
    else if(gamma > 20 || gamma < - 20)
    {
        document.getElementById("status").innerHTML = "vibrating off";
    }
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.canvas.width  = window.innerWidth;//resize canvas to whatever window dimensions are
context.canvas.height = window.innerHeight;
context.translate(canvas.width / 2, canvas.height / 2); //put 0,0,0 origin at center of screen instead of upper left corner

function degToRad(deg)// Degree-to-Radian conversion
{
    
    return deg * Math.PI / 180;
}


//returns a 3D box like object centered around the origin. There are more than 8 points for this cube as it is being made by chaining together a strip of triangles so points are redundant at least 3x. Confusing for now (sorry) but this odd structure comes in handy later for transitioning into webgl
function makeRect(width,height,depth)
{
    var newObj={};
    var hw=width/2;
    var hh=height/2;
    var hd=depth/2;
    newObj.vertices=[  [-hw,hh,hd],[hw,hh,hd],[hw,-hh,hd],//first triangle
          [-hw,hh,hd],[-hw,-hh,hd],[hw,-hh,hd],//2 triangles make front side
          [-hw,hh,-hd],[-hw,hh,hd],[-hw,-hh,-hd], //left side
          [-hw,hh,hd],[-hw,-hh,hd],[-hw,-hh,-hd],
          [hw,hh,-hd],[hw,hh,hd],[hw,-hh,-hd], //right side
          [hw,hh,hd],[hw,-hh,hd],[hw,-hh,-hd],
          [-hw,hh,-hd],[hw,hh,-hd],[hw,-hh,-hd],//back
          [-hw,hh,-hd],[-hw,-hh,-hd],[hw,-hh,-hd],
          [-hw,hh,-hd],[hw,hh,-hd],[hw,hh,hd],//top
          [-hw,hh,-hd],[-hw,hh,hd],[hw,hh,hd],
          [-hw,-hh,-hd],[hw,-hh,-hd],[hw,-hh,hd],//bottom
          [-hw,-hh,-hd],[-hw,-hh,hd],[hw,-hh,hd]
    ];
    
    return newObj;
}

var cube=makeRect(canvas.width/5,canvas.width/5,canvas.width/5);
cube.color="purple";
var xAxis=makeRect(440,10,10);
xAxis.color="green";
var yAxis=makeRect(10,440,10);
yAxis.color="red";
var zAxis=makeRect(10,10,440);
zAxis.color="blue";

//render loop
function renderLoop()
{
  requestAnimationFrame( renderLoop );//better than set interval as it pauses when browser isn't active
  context.clearRect( -canvas.width/2, -canvas.height/2, canvas.width, canvas.height);//clear screen x, y, width, height
//create some fake data in case web page isn't being accessed from a mobile or gyro enabled device
  if(!( window.DeviceOrientationEvent && 'ontouchstart' in window))//only happens on desktops
  {
    this.fakeAlpha = (this.fakeAlpha || 30)+ .0;//z axis – use 0 to turn off rotation, alpha start at 30
    this.fakeBeta = (this.fakeBeta || 30)+ .0;//x axis  – use 0 to turn off rotation, beta start at 30
    this.fakeGamma = (this.fakeGamma || 0)+ 0.2;//y axis
    
    
    processGyro(this.fakeAlpha,this.fakeBeta,this.fakeGamma);
  }
  renderObj(cube);
  renderObj(xAxis);
  renderObj(yAxis);
  renderObj(zAxis);
}
renderLoop();
function renderObj(obj)//renders an object as a series of triangles
{
    var rotatedObj=rotateObject(obj);
    
    context.lineWidth = 1;
    context.strokeStyle = obj.color;
    
    
    for(var i=0 ; i<obj.vertices.length ; i+=3)
    {
        for (var k=0;k<3;k++)
        {
          var vertexFrom=rotatedObj.vertices[i+k];
          
          var temp=i+k+1;
          if(k==2)
              temp=i;
              
          var vertexTo=rotatedObj.vertices[temp];        
          context.beginPath();
          context.moveTo(scaleByZ(vertexFrom[0],vertexFrom[2]), -scaleByZ(vertexFrom[1],vertexFrom[2]));
          
      context.lineTo(scaleByZ(vertexTo[0],vertexTo[2]), -scaleByZ(vertexTo[1],vertexTo[2]));
          context.stroke();
        }
    }
}

function scaleByZ(val,z)//takes either an x or a y value, and also the z value
{
    var focalLength=900; //pick any value that looks good
    var scale= focalLength/((-z)+focalLength);
    return val*scale;
}
function rotateObject(obj) //rotates obeject
{
    var newObj={};
    newObj.vertices=[];
    for(var i=0 ; i<obj.vertices.length ; i++)
    {
      newObj.vertices.push(rotatePointViaGyroEulars(obj.vertices[i]));
    }
    return newObj;
}    

function rotatePointViaGyroEulars(ra) //rotates 3d point based on eular angles
{
    var oldX=ra[0];
    
    var oldY=ra[1];
    
    var oldZ=ra[2];
    
    

    //rotate about z axis
    
    var newX = oldX * Math.cos(-degToRad(deviceOrientationData.alpha)) - oldY * Math.sin(-degToRad(deviceOrientationData.alpha));
    
    var newY = oldY * Math.cos(-degToRad(deviceOrientationData.alpha)) + oldX * Math.sin(-degToRad(deviceOrientationData.alpha));
    
    
    //rotate about x axis
    
    oldY=newY;
    
    newY = oldY * Math.cos(-degToRad(deviceOrientationData.beta)) - oldZ * Math.sin(-degToRad(deviceOrientationData.beta));
    
    var newZ = oldZ * Math.cos(-degToRad(deviceOrientationData.beta)) + oldY * Math.sin(-degToRad(deviceOrientationData.beta));
    
    
    //rotate about y axis
    
    oldZ=newZ;
    
    oldX=newX;
    
    newZ = oldZ * Math.cos(-degToRad(deviceOrientationData.gamma)) - oldX * Math.sin(-degToRad(deviceOrientationData.gamma));
    
    newX = oldX * Math.cos(-degToRad(deviceOrientationData.gamma)) + oldZ * Math.sin(-degToRad(deviceOrientationData.gamma));
    
    
    return [newX,newY,newZ];    
}
    
      
</script>
</body>
</html>
And this is the final look on computer:
Mobile Gyroscope
Published:

Mobile Gyroscope

Published: