Flying memes

HTML5 Augmented Reality: fuzzy results

I spent a few hours trying to figure out how to deal with the brand new deviceorientation API in order to obtain a nice Augmented Reality effect. First I searched on how to convert Euler Angles to Cartesian Coordinates and I found a nice article about that, then I downloaded the very nice Sylvester library which lets you compute matrix operations in Javascript.

Then I write this code:


Demo1 = function(){
  var demo1 = {};
  
  demo1.generatePoints = function(numero,dimensioni_box){
    var points = [];
    for(var i=0;i < numero; i++){
      var x0 = Math.floor((Math.random()-0.5)*(dimensioni_box)),
          y0 = Math.floor((Math.random()-0.5)*(dimensioni_box)),
          z0 = Math.floor((Math.random()-0.5)*(dimensioni_box)),
          x1 = x0 + 5;
          y1 = x1 + 5;
          z1 = z0;
      
      points.push(
        [$M([[x0],[y0],[z0]]), $M([[x1],[y1],[z1]])]
      );
    }
    return points;
  }
  
  demo1.init = function(evento){
    // #drawboard is a canvas element
    demo1.canvas = document.querySelector('#drawboard');
    demo1.canvas.width  = 320;
    demo1.canvas.height = 480;
    demo1.context = demo1.canvas.getContext('2d');
    demo1.points =  demo1.generatePoints(200, 100);
  };
  
  demo1.resetCanvas = function(){
     demo1.context.fillStyle = '#FFFFFF';
     demo1.context.fillRect(0,0, demo1.canvas.width, demo1.canvas.height);
     demo1.context.fillStyle = '#000000';
  }
  
  demo1.cambioOrientamento = function(evento){
    demo1.resetCanvas();
        
    var heading  = ((evento.alpha > 180 ? evento.alpha - 360 : evento.alpha) * Math.PI) / 180.0;
    var attitude = (evento.beta  *  Math.PI)     / 180.0;
    var bank     = (evento.gamma * (Math.PI/2.0)) / 90.0;
    
    var ch = Math.cos(heading),     sh = Math.sin(heading),
        ca = Math.cos(attitude),    sa = Math.sin(attitude),
        cb = Math.cos(bank),        sb = Math.sin(bank);
    
    var rotation_matrix = $M([
          [ch*ca  , -ch*sa*cb + sh*sb , ch*sa*sb + sh*cb    ],
          [sa      , ca*cb             , -ca*sb             ],
          [-sh*ca , sh*sa*cb + ch*sb  , -sh*sa*sb + ch*cb   ]
    ]);
    
    for(var i=0; i < demo1.points.length; i++){
      var pr  = rotation_matrix.x(demo1.points[i][0]);
      var x   = 160 + ((640*pr.e(1,1)) / (pr.e(3,1)));
          y   = 240 - ((640*pr.e(2,1)) / (pr.e(3,1)));
      demo1.context.fillRect(x,y,10,10);
    }
  };
  return demo1;
}();

window.addEventListener('load',Demo1.init,false);
window.addEventListener('deviceorientation',Demo1.cambioOrientamento,false);

If you have a device which supports the deviceorientation API (eg: iPhone4) you can test the running example here: http://sandropaganotti.com/wp-content/goodies/mobile/demo1.html as you might notice is still far from perfect but at the moment I've no time to refine it and so I have to leave it 'as is' ( still somehow nice IMHO ).

If someone got a clues on this please e-mail me at: sandro.paganotti@gmail.com

Tags: ,