Search Unity

CardBoard, VR by Google for Android, only $45

Discussion in 'Android' started by davbar9, Jun 26, 2014.

  1. davbar9

    davbar9

    Joined:
    May 19, 2014
    Posts:
    62

    Attached Files:

  2. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    Someone make Unity support this, or maybe i can find someone who can
     
  3. Evil-Otaku

    Evil-Otaku

    Joined:
    Oct 17, 2012
    Posts:
    72
  4. zpr

    zpr

    Joined:
    May 29, 2014
    Posts:
    1
    Durovis has a similar product called Dive which they are selling on their website now, and it has a free Android/iOS Unity plugin that is literally drag-and-drop simple. It'll work with any mobile VR headset including Google Cardboard.

    https://www.durovis.com/sdk.html

    Thanks, almost bought one on eBay for like $50... Finding proper lenses was a horrible pain. Eventually found some online that ended up being around $15 including shipping. While waiting for the lenses, I popped the lenses out of some old binoculars (ended up not being the proper size). I do not regret buying the lenses anyway since they will hopefully ship faster than 4-6 weeks and I just cannot bear to wait that long. Maybe I will buy this cardboard kit anyway just to have an extra set, at least for the lenses (or maybe a family member).
     
    davbar9 likes this.
  5. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    Cheers! I was thinking of using the oculus sdk but that will probably be just the ticket

    I found a site in the uk selling plano-convex lenses at the right focal length for £2.90 each so hopefully they will do the job, bought 4
     
  6. davbar9

    davbar9

    Joined:
    May 19, 2014
    Posts:
    62
    Thanks for the sdk info! I think, is perfect for Cardboard.
     
  7. peepalala

    peepalala

    Joined:
    Jul 7, 2014
    Posts:
    1
  8. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    I've been stuck into making an android attempt for this using OpenDive's sdk - it's great fun! I wish my first effort at the headset wasnt so shabby though aha
     
  9. ACS

    ACS

    Joined:
    Jul 7, 2014
    Posts:
    5
    Anyone have a reliable method for getting button-like input from the magnet slider on the side of the cardboard device?
     
  10. Evil-Otaku

    Evil-Otaku

    Joined:
    Oct 17, 2012
    Posts:
    72
    The magnet needs to be right next to the phone. I had better luck sliding the magnet forward instead of down.
     
  11. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    If not using Google's SDK i've found getting the input a matter of reading the magnetometer (re. compass) changes between frames using the Unity api - the change in magnetic field is used to get an input (measure the 'swing') when the magnet is moved

    So far i'm just tapping the phone with a magnet as i haven't suitable magnets for Cardboard, but this is working as reliable input, you might want to write a little bit of code to visualise the changes to the raw magnetometer moving a nearby magnet makes, and basing the values for an input reading on that.

    It goes without saying that any magnet alters this and quite a lot of things are magnetic
     
  12. ACS

    ACS

    Joined:
    Jul 7, 2014
    Posts:
    5
    Thanks for the reply. The issue with reading from the compass is that its input also changes when you move the device for head-tracking purposes. I'm still working on a method to compare compass data to orientation from the gyro to find a discrepancy, but the fact that the raw input isn't very intuitive (I suspect quaternions are the culprit) makes the math difficult.

    So far my best attempt has been comparing the rate of change of the compass and gryo, and if the gyro doesn't move but the compass does, register that as magnetic input. However, it has issues when the magnet is moved back and forth quickly since I'm only looking at the magnitude.

    I like the idea of comparing the compass orientation to what it "should" be to detect magnetic fields. I'm just having difficulty figuring out how to code that.
     
  13. ACS

    ACS

    Joined:
    Jul 7, 2014
    Posts:
    5
    Side Note: Even if the performance is somewhat poor, does anyone know of any free shaders that replicate the fisheye distortion from the pro version? I need it for lens correction. Its literally the only pro feature I need and so I can't justify shelling out for it.
     
  14. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    Ahh yep, i just cached the initial value for the magnetic north and used this and the latest orientation based on that to factor in when a swing considerable enough happens to count as an input - getting the magnetic north on startup and the raw magnetometer reading is in the Input.compass api and the raw value is measured in microteslas, whatever they are, so aren't relative to quaternions i don't think?

    http://docs.unity3d.com/ScriptReference/Compass.html

    With GPS you can get a completely solid due north to base orientation on, to avoid issues with rapid switching of input I think I just lock the next input until the delta caused by the magnet is back below whatever threshold you set for a readable input. I can post my code if it helps, it may be lacking and I may be missing the point, but it's been fine for exploring and manipulating the environment in a walk-em-up sense kind of pace, it does lack anything clever though, no averaging or using the gyroscope, works in the above circumstance however
     
  15. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    Also, not free but affordable, I can supply you with the thing I made to get OR running on Unity Free that has the shader stuff needed but requires https://www.assetstore.unity3d.com/en/#!/content/11614 - it is very slow but might do what you need
     
  16. YoDevil

    YoDevil

    Joined:
    Jun 14, 2013
    Posts:
    1
    Yes, can you please post the code? :)
     
  17. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    Here's the code lifted verbatim, so it's in a use case here.. there's really nothing to it, sorry if it's a bit dim seeming, code's not remotely my strong point, and wholly prototypical and I try to get others to do it if possible

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayerInteraction : MonoBehaviour
    5. {
    6.  
    7.     public AIPath player;
    8.     public float pushPower = 2.0F;
    9.     public LayerMask walkable;
    10.     public float interactDistance;
    11.     public Camera rayCam;
    12.     public GameObject reticle;
    13.     public float reticleSpeed;
    14.     public Color reticleClicked;
    15.     public Color reticleInteractive;
    16.     public Color reticleInteractiveNear;
    17.     public Color reticleInteracting;
    18.     public float magDirChange;
    19.     public int inputDelayFrames;
    20.     public GameObject interactLabel;
    21.     private float previousMagneticNorth;
    22.     private Color reticleStartCol;
    23.     private int ticker;
    24.     private bool interacting;
    25.     private GameObject activeObject;
    26.     private GameObject UIRoot;
    27.     private RaycastHit hit;
    28.  
    29.     // Use this for initialization
    30.     void Start()
    31.     {
    32.         Input.compass.enabled = true;
    33.         previousMagneticNorth = Input.compass.magneticHeading;
    34.         reticleStartCol = reticle.renderer.material.color;
    35.         UIRoot = GameObject.FindGameObjectWithTag("UIRoot");
    36.         interactLabel = Instantiate(interactLabel) as GameObject;
    37.         interactLabel.transform.parent = UIRoot.transform;
    38.         interactLabel.SetActive(false);
    39.     }
    40.  
    41.     // Update is called once per frame
    42.     void FixedUpdate()
    43.     {
    44.         if (interacting == false)
    45.         {
    46.             if (reticle.renderer.material.color != reticleStartCol) ticker++;
    47.             if (ticker > inputDelayFrames) { reticle.renderer.material.color = reticleStartCol; ticker = 0; if (interactLabel.activeSelf == true) interactLabel.SetActive(false); }
    48.  
    49.  
    50.             Ray ray = rayCam.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
    51.  
    52.             if (Physics.Raycast(ray, out hit, walkable))
    53.             {
    54.                 reticle.transform.position = Vector3.Lerp(reticle.transform.position, hit.point, Time.deltaTime * reticleSpeed);
    55.  
    56.                 if (ticker == 0)
    57.                 {
    58.                     if (hit.collider.gameObject.tag == "Interactive")
    59.                     {
    60.                         if ((hit.point - transform.position).sqrMagnitude < interactDistance * 2)
    61.                         {
    62.                             reticle.renderer.material.color = reticleInteractiveNear;
    63.                         }
    64.                         else
    65.                         {
    66.                             reticle.renderer.material.color = reticleInteractive;
    67.                         }
    68.                         interactLabel.SetActive(true);
    69.                         interactLabel.transform.position = hit.point;
    70.                         interactLabel.GetComponentInChildren<UILabel>().text = hit.collider.gameObject.GetComponent<Interaction>().tipName;
    71.                     }
    72.                 }
    73.  
    74.                 if (Mathf.Abs(Input.compass.magneticHeading - previousMagneticNorth) > 30.0f || Input.GetMouseButtonDown(0) == true)
    75.                 {
    76.                     if (hit.collider.gameObject.tag == "Interactive" && (hit.point - transform.position).sqrMagnitude < interactDistance)
    77.                     {
    78.                         print((hit.point - transform.position).sqrMagnitude);
    79.                         interacting = true;
    80.                         interactLabel.SetActive(false);
    81.                         reticle.renderer.material.color = reticleInteracting;
    82.                         activeObject = hit.collider.gameObject;
    83.                         activeObject.SendMessage("Interact");
    84.                     }
    85.  
    86.                     if (hit.collider.gameObject.tag != "Interactive")
    87.                     {
    88.                         player.target.position = hit.point;
    89.                         reticle.renderer.material.color = reticleClicked;
    90.                     }
    91.                     previousMagneticNorth = Input.compass.magneticHeading;
    92.                 }
    93.             }
    94.         }
    95.  
    96.         if (interacting == true)
    97.         {
    98.             if (activeObject.GetComponent<Interaction>().freezeReticule)
    99.             {
    100.                 if (Mathf.Abs(Input.compass.magneticHeading - previousMagneticNorth) > 30.0f || Input.GetMouseButtonDown(0) == true)
    101.                 {
    102.                     Ray ray = rayCam.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
    103.  
    104.                     if (Physics.Raycast(ray, out hit, walkable))
    105.                     {
    106.                         if (hit.collider.gameObject.tag != "Interactive")
    107.                         {
    108.                             interacting = false;
    109.                             activeObject.SendMessage("Deactivate");
    110.                             activeObject = null;
    111.                         }
    112.                     }
    113.                 }
    114.             }
    115.             if (activeObject && !activeObject.GetComponent<Interaction>().activated)
    116.             {
    117.                 interacting = false;
    118.                 activeObject = null;
    119.             }
    120.         }
    121.     }
    122.  
    123.     void OnControllerColliderHit(ControllerColliderHit hit)
    124.     {
    125.         Rigidbody body = hit.collider.attachedRigidbody;
    126.         if (body == null || body.isKinematic)
    127.             return;
    128.  
    129.         if (hit.moveDirection.y < -0.3F)
    130.             return;
    131.  
    132.         Vector3 pushDir = new Vector3(hit.moveDirection.x, 0, hit.moveDirection.z);
    133.         body.velocity = pushDir * pushPower;
    134.     }
    135. }
    136.  
     
  18. teina

    teina

    Joined:
    Jul 18, 2014
    Posts:
    1
  19. schoen08

    schoen08

    Joined:
    Sep 4, 2012
    Posts:
    6
  20. Dnegus3d

    Dnegus3d

    Joined:
    Jul 29, 2014
    Posts:
    3
    Hey just downloaded your game its super fun!
     
  21. R_maX

    R_maX

    Joined:
    Jul 31, 2014
    Posts:
    1
  22. pyratej

    pyratej

    Joined:
    Jul 13, 2012
    Posts:
    12
    So i've tried to boil this down to my uses in JS. (and maybe that was a bad idea in the first place). It seems to be working with the magnet but also seems to fire by turning or shaking your head. Is there something i'm missing here? The head tracking is currently provided by the Durovis plug-in and I'm really not sure how the separate the compass readings from the gyro.

    Code (JavaScript):
    1. #pragma strict
    2.  
    3. var readOut : GUIText;
    4.  
    5. var previousMagneticNorth : float;
    6.  
    7. var swivelGun : GameObject;
    8.  
    9. function Start () {
    10.     Input.compass.enabled = true;
    11.     previousMagneticNorth = Input.compass.magneticHeading;
    12. }
    13.  
    14. function FixedUpdate () {
    15.  
    16.     if (Mathf.Abs(Input.compass.magneticHeading - previousMagneticNorth) > 30.0){
    17.         print("CLICK");
    18.         swivelGun.SendMessageUpwards("FireTheCannon");
    19.        
    20.         previousMagneticNorth = Input.compass.magneticHeading;
    21.     }
    22.    
    23.     readOut.text = previousMagneticNorth.ToString();
    24. }
    What say you mates?
     
  23. ACS

    ACS

    Joined:
    Jul 7, 2014
    Posts:
    5
    Thanks for the responses. I managed to get the magnet working (right now it's reeeeeeeally ghetto) but I haven't converted it into any clean code yet. Right now I have a box that has an upward force applied to it when it detects a large amount of compass movement and little to no gyro change. When it gets high enough to hit another box I trigger an action, and I adjust the mass of it to change the sensitivity of the magnet.

    Its kinda gross and I know I could boil it down to a single clean component that does the equivalent math. I just haven't yet.
     
  24. Jesse_Pixelsmith

    Jesse_Pixelsmith

    Joined:
    Nov 22, 2009
    Posts:
    296
    I'm very interested in this, just ordered my cardboard and should get here in a few days, then I will contribute what I can - keep it coming guys!

    Oh - and would I need Android Pro to get this to work optimally? I have Unity 5 Pro but haven't spent the 1.5k yet to upgrade to android pro (haven't had a need to yet), hopefully I can at least prototype with this without having to do so.
     
    Last edited: Aug 8, 2014
  25. zark

    zark

    Joined:
    Aug 14, 2014
    Posts:
    1
    has anyone able to use a gamepad as a means to control the character im fairly new to unity and has a game in mind that is suitable with cardboard and needs to use the gamepad as a means to make a character move thanks
     
  26. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    My above code was a little dim, after returning to it while working on various things i found basing the magnetometer click on a magnet reading while watching the gyro wasnt changing a lot helped make it more accurate

    Overall however I think i'm just going to move as much of the google sdk over to unity anyways as they do the whole thing a bunch better and moving it to Unity means cardboard on all the phones, i'll post it as a freebie if it gets anywhere, at the very least basics will prove useful. I'm finding the dorovis thing a bit of an annoyance and the insistence of the splash screen in the license is a bind
     
  27. pyratej

    pyratej

    Joined:
    Jul 13, 2012
    Posts:
    12
  28. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    That actually might be a tad faster than my efforts, cheers!

    Edit: Well, had a look and I guess currently it's not quite set for a full use, im coming from the other direction and implementing the datatypes and other utils for using Cardboard SDK's orientation and overall sensor implementation, which avoids any licensing stuff from Dive and wotnot. I'll keep going with my stuff as I was and if anyone knocks out anything superior or more complete, faster, good stuff!
     
  29. scottharber

    scottharber

    Joined:
    May 14, 2014
    Posts:
    42
    Hello all,

    Regarding the magnet button, I have an incredibly filthy method for reading the magnet, which seems to be about 99% reliable. It can determine when the button is held down, regardless of the angle of the device or by how much it's moving.

    I use the magnitude of the raw vector to determine when the button has been pressed. When the button is pressed, the magnitude will increase by roughly 2 to 5 times, depending on the strength/proximity of the magnet to the compass. Whereas fluctuations in the gyro will cause the magnitude to change by more than 23 times. So the way that I solve the problem is by having two concurrently-running scripts.

    The first script remembers a baseline magnitude of the raw vector when the magnet is not pressed (in my code, it's called the “initialrv”). If the magnitude changes massively, then the first script refreshes the initialrv to an up-to-date value. This prevents sudden changes in the magnitude readings from the gyro.

    The second script reads the current magnitude of the raw vector, and tests it against the initialrv. If the current magnitude is more than double the initial magnitude, then the button is being held down.

    I have included sample code here...

    Code (JavaScript):
    1. // * “Globals” script *
    2.  
    3. static var initialrv : int = 0; // Raw compass vector to test the magnet against
    4. static var prevrv : int = 0; // Raw compass vector to verify that initialrv is valid
    5.  
    6. static var initialrot : ScreenOrientation;
    7.  
    8. function Start ()
    9. {
    10. initialrot = Screen.orientation;
    11. Input.compass.enabled = true;
    12. }
    13.  
    14.  
    15. function Update () {
    16. // Catch if the initialrv is completely wrong
    17. // (sometimes the magnitude can jump from
    18. // 15 to 400, depending on how the player
    19. // rotates the device).
    20. //
    21. if (prevrv > initialrv * 23)
    22. {
    23. initialrv = Mathf.RoundToInt(Input.compass.rawVector.magnitude);
    24. }
    25.  
    26. // Catch if the user flips the screen to change the orientation
    27. //
    28. if (initialrot != Screen.orientation || initialrv == 0)
    29. {
    30. initialrot = Screen.orientation;
    31. initialrv = Mathf.RoundToInt(Input.compass.rawVector.magnitude);
    32. }
    33.  
    34. // Catch if the magnitude has fallen by a
    35. // huge amount since the last update
    36. //
    37. var vectest = Mathf.RoundToInt(Input.compass.rawVector.magnitude);
    38. if (initialrv > vectest * 23)
    39. {
    40. initialrv = Mathf.RoundToInt(Input.compass.rawVector.magnitude);
    41. }
    42.  
    43.  
    44. // Refresh prevrv to test against at the start of the next update
    45. //
    46. prevrv = Mathf.RoundToInt(Input.compass.rawVector.magnitude);
    47. }
    Code (JavaScript):
    1. //* “GameLogic” script *
    2.  
    3. // assuming the initialrv from the global script is roughly
    4. // consistent with the current magnitude before a button
    5. // is pressed, we can test against it. If the magnitude raises
    6. // two-fold, it indicates that the magnetic button has been
    7. // pressed. If the magnitude raises by 23 times or more, it
    8. // indicates a false-positive, at which point the initialrv is reset.
    9. //
    10.  
    11. var vectest = Mathf.RoundToInt(Input.compass.rawVector.magnitude);
    12.  
    13. if (vectest > Globals.initialrv * 2)
    14. {
    15. // Magnet button down
    16. }
    17.  
     
  30. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    Nice work! In my own time i've moved the sdk magnet and orientation code over, i just havent tested it properly yet and i couldn't figure out a graceful way for it to send messages other than SendMessage(). So if people are fine dealing with a big lump of shoddy code then i can investigate getting it working properly
     
  31. nandonevess

    nandonevess

    Joined:
    Aug 9, 2014
    Posts:
    1
    Last edited: Aug 28, 2014
  32. Max-Pixel

    Max-Pixel

    Joined:
    Sep 3, 2013
    Posts:
    8
    pyratej's buddy's script worked great for me. I made a few implementation changes to it, and sent him a pull request, actually.
     
  33. scottharber

    scottharber

    Joined:
    May 14, 2014
    Posts:
    42
  34. Deleted User

    Deleted User

    Guest

    Hi,

    I been looking around in the forums but does not seem to be any condensed information. Can anyone please share your development process for creating apps that work with Google Cardboard? What tools are you using? what version of Unity, did you need an SDK, from where? Anything else, how you need to build/publish the game and how you get it into the phone (Nexus5)? I appreciate if you can share some of your experiences and processes.

    Thanks,
     
  35. scottharber

    scottharber

    Joined:
    May 14, 2014
    Posts:
    42
    Hi arkitektura,

    As sheer coincidence would have it, I was already writing something similar for my blog.

    http://www.sc0ttgames.com/?p=293

    TL;DR version: Standard Unity + the Durovis Dive plugin is all you need. Beyond that, just compile it as you would any other Android app.
     
  36. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    Using the Dive has a few drawbacks, i was finding the input would skew and jitter quite wildly at times with no access to the plugin code to unearth what was up, the license requires the Durovis splash image at start and as far as I could tell involves no barrel distortion post process. The Cardboard works without the post process (i haven't tested but i imagine my oculus possibly does too), but that's pulling short of the intended effect

    Does anyone have any confirmation of Dive working on iOs?
     
  37. scottharber

    scottharber

    Joined:
    May 14, 2014
    Posts:
    42
    I have follow up questions:

    Is there an option for anything other than the Dive?

    Also, how would the barrel distortion work? I heard that image effects didn't work on Unity mobile?
     
  38. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    Image effects work fine for mobile with Unity pro, worth keeping in mind if you wish to use it. There are several third party solutions (Or you can figure it out) for doing image effects in free but this is very slow. Currently there's no alternative to Dive although all the required functionality is in the Unity API. I'm talking to a pal tonight (based on his message) about getting my port of the Cardboard SDK in good shape for a Unity outing, it needs some more intelligent organisation and a more elegant way to handle events. Im not really a great programmer at all but have done the heavy lifting getting the core areas in Unity-friendly shape, hopefully, i'll see what he says, with any luck a Unity flavour of the SDK may be available quite soon

    Your tutorial is absolutely fine by the way, and good pointer for getting started right now
     
  39. Deleted User

    Deleted User

    Guest

    Thank you for the reply scottharber. I manage to attached the "Dive" cameras to the First Person Controller.
    Question: How can you move around an scene using Google Cardboard? Has anyone figure out this? I understand that if you are using a Oculus you will be able to use a keyboard or game controller to be able to move forward, backwards etc.
     
  40. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    My interaction system uses A* pathfinding - look where you want to go and if it has a 'walkable' collider and isnt interactive, on clicking the magnet the hit location is set as the new target for the A* to path to and the viewer follow it
     
  41. scottharber

    scottharber

    Joined:
    May 14, 2014
    Posts:
    42
    What lazygunn said. :)

    In theory, you could go even simpler, and just have the player move in the direction the camera is facing when the magnet is held down.

    transform.Translate(camera.transform.forward);

    Though obviously, to use this, you would have to do some stuff to the forward vector to stop the character from translating through the floor or into the air.
     
  42. lazygunn

    lazygunn

    Joined:
    Jul 24, 2011
    Posts:
    2,749
    I'm wondering if I should have it so a single click uses A* but a double click puts you in reverse, a click during reverse stops you, and in my case where i want to drag things, another click to drop the object. Hmm. Cheers for the ideas
     
  43. scottharber

    scottharber

    Joined:
    May 14, 2014
    Posts:
    42
    Whoa. Your game involves moving forwards, backwards, stopping, and grabbing items. That's pretty involved for a system with only one button! I'm quite curious about what you're making now. :)
     
  44. Mouks

    Mouks

    Joined:
    Apr 6, 2014
    Posts:
    1
    I see some demos use game controllers for input which connects via otg cable or bluetooth.
    Would it be possible to connect 2 phones via Bluetooth and using the second phone for input. Moving forward and backward and an action button.
     
  45. davbar9

    davbar9

    Joined:
    May 19, 2014
    Posts:
    62
  46. 128bit

    128bit

    Joined:
    Oct 8, 2014
    Posts:
    117
    Im experimenting right now with vuforia Augmented Reality combined with googles Cardboard, it´s realy fun! :D
     
  47. davbar9

    davbar9

    Joined:
    May 19, 2014
    Posts:
    62
    What assets you use?
     
  48. 128bit

    128bit

    Joined:
    Oct 8, 2014
    Posts:
    117
    For augmented reality only the Vuforia plugin. I let it display a chess board+ai when marker is detected, so its some kind of AR Chess for the Cardboard:D
     
    Last edited: Oct 8, 2014
  49. davbar9

    davbar9

    Joined:
    May 19, 2014
    Posts:
    62
    What you use to run Google Cardboard and motion sensor?
     
  50. 128bit

    128bit

    Joined:
    Oct 8, 2014
    Posts:
    117
    Im using 2 default unity cameras, with viewports set to render those in SBS view, nothing google cardboard spefically. I dont need any motion sensors, cause its an SBS augmented reality application, the camerastream always shows automatically where you looking at. So rendering the Vuforia camerastream to textures/on a plane and let the cameras looking at the plane is enough. No need for headtracking in augmented reality apps.