This translation is incomplete. Please help translate this article from English.

WebVR API on hieno lisä webkehittäjän työkaluihin. Sen avulla WebGL- näkymä (scene) voidaan esittää Oculus Riftin and HTC Viven tapaisissa VR-näytöissä. Mutta miten pääset alkuun VR appsien tekemiseen webbiin? Tämä juttu opastaa sinut perusteisiin.

Huom: WebVR APIn vakain versio — 1.1 — on vasta implementoitu Firefox 55:een (Windowsin release-versio, Mac OS X :ssa vain 'Nightly'), ja sen saa myös Chrome:en käytettäessä Google Daydream -laitteistoa. Speksistä on myös tuoreempi versio — 2.0 — mutta se on kovin keskeneräinen. Lisätietoja viimeisimmästä speksistä löytyy linkistä WebVR Spec Version List.

Aloitus

Päästäksesi alkuun tarvitset:

  • Tuetun VR-laitteiston.
    • halvin vaihtoehto on mobiililaite, tuettu selain, ja silmikkonäyttö, johon mobiililaitteen saa asetettua (esim. Google Cardboard). Tämä ei vastaa käyttökokemukseltaan aivan tarkoitukseen suunniteltua laitteistoa, mutta selviät ostamatta teho-PC:tä tai erityistä VR-näyttöä.
    • VR-laitteisto saattaa olla hinnakas, mutta sillä saadaan parempi käyttökokemus. Parhaiten WebVR-yhteensopivia laitteita ovat tällä hetkellä HTC VIVE ja The Oculus Rift. webvr.info :n etusivulla on lisätietoa laitteiden tarjonnasta ja selaintuesta niille.
  • Mahdollisesti vaaditun riittävän tehokkaan tetokoneen VR-näkymien prosessointiin ja näyttämiseen VR-laitteistollesi. Koneen speksejä varten tutki sen VR-laitteiston vaatimuksia (e.g. VIVE READY Computers), jonka aiot hankkia.
  • Tuettu selain tulee olla asennettu — uusin Firefox Nightly tai Chrome ovat parhaat vaihtoehdot tällä hetkellä, PC:lle tai mobiiliin.

Kun laitteisto ja ohjelmistot on asennettu, voit testata, toimiiko kokoonpanosi WebVR:n kanssa tästä linkistä - simple A-Frame demo, ja näet, saadaanko näkymä näkyviin ja pääsetkö VR-moodiin oikean alareunan painikkeella.

A-Frame on paras vaihtoehto päästä tekemään nopeasti WebVR-yhteensopivia 3D-näkymiä, ilman että tarvitsee ymmärtää rivikaupalla uutta JavaScript -koodia. Se ei kuitenkaan opeta, kuinka raaka WebVR API toimii ja siihen paneudummekin seuraavaksi.

Demon esittely

WebVR API :n toiminnan esdittelemiseksi tutustumme puhtaasti webgl:ää sisältävään esimerkkiimme, joka näyttää vähän tältä:

Huom: Demon lähdekoodi - source code - löytyy GitHubista ja livelinkki siihen on tässä: view it live.

Huom: Ellei WebVR ei ala toimia selaimessa, varmista, että sitä ajetaan grafiikkakortin kautta. Esimerkiksi NVIDIA :lla sen omassa ohjauspaneelissa on pikavalikkovalinta Firefox, josta valitaan Run with graphics processor > High-performance NVIDIA processor.

Demossa on kaikkien WebGL-demojen äiti — pyörivä  3D-kuutio. Toteutimme sen puhtaasti WebGL API :n koodilla. Tässä ei käsitellä perus JavaScriptiä tai WebGL:ää, vaan pelkästään WebVR osia.

Demosta löytyy myös:

  • Painike, jolla näkymä saadaan päälle VR-näyttöön (ja pois).
  • Painike, joka näyttää (ja piilottaa) VR:n 'pose' -tiedot - eli silmikon sijainnin ja suunnan - reaaliajassa.

Kun tutustut lähdekoodin päätiedostoon - main JavaScript file - löydät WebVR-osat koodista kommenttien "WebVR" tekstien avulla.

Huom: JavaScriptin ja WebGL:n perusteista lisätietoja löytyy tutoriaaleista JavaScript learning material ja WebGL Tutorial.

Miten se toimii?

Tässä vaiheessa katsotaan koodin WebVR-osien toiminta.

Tyypillinen (yksinkertainen) WebVR sovellus toimii näin:

  1. Navigator.getVRDisplays() hakee viittauksen VR-näyttöösi.
  2. VRDisplay.requestPresent() :ä käytetään käynnistämään esittäminen VR-näytölle.
  3. WebVR:n omaa VRDisplay.requestAnimationFrame() -metodia käytetään suorittamaan sovelluksen renderöintisilmukkaa näytölle sopivalla virkistystaajuudella.
  4. Renderöintisilmukassa haet ruudun näyttämiseen vaaditun datan (VRDisplay.getFrameData()), piirrät näytettävän skenen kahdesti — molemmille silmille — ja toimitat renderöidyn näkymän näytölle käyttäjälle näytettäväksi metodilla (VRDisplay.submitFrame()).

Alla olevissa kappaleissa tutustutaan webgl-demoihimme yksityiskohtaisemmin ja nähdään tarkemmin, missä edellä mainittuja ominaisuuksia käytetään.

Aloitetaan muuttujilla

Ensimmäinen esimerkki WebVR:n käytöstä näkyy alla olevassa koodissa:

// WebVR variables

var frameData = new VRFrameData();
var vrDisplay;
var btn = document.querySelector('.stop-start');
var normalSceneFrame;
var vrSceneFrame;

var poseStatsBtn = document.querySelector('.pose-stats');
var poseStatsSection = document.querySelector('section');
poseStatsSection.style.visibility = 'hidden'; // hide it initially

var posStats = document.querySelector('.pos');
var orientStats = document.querySelector('.orient');
var linVelStats = document.querySelector('.lin-vel');
var linAccStats = document.querySelector('.lin-acc');
var angVelStats = document.querySelector('.ang-vel');
var angAccStats = document.querySelector('.ang-acc');
var poseStatsDisplayed = false;

Lyhyet selitykset ovat siis tarpeen:

  • frameData sisältää VRFrameData olion, joka on tehty VRFrameData() -muodostimella. Tämä on alkuaan tyhjä, mutta sisältää myöhemmin VR-näytölle näytettävien ruutujen renderöintiin tarvittavat tiedot, ja ne päivitetään aina renderöintisilmukassa uudelleen.
  • vrDisplay on alkuun alustamaton, mutta siinä on myöhemmin viittaus VR-silmikkoomme (VRDisplay — joka on API:n keskeinen ohjattava kohde).
  • btn ja poseStatsBtn viittaavat sovelluksen ohjaamiseen käytettyihin painikkeisiin.
  • normalSceneFrame ja vrSceneFrame ovat aluksi alustamattomia, mutta myöhemmin viittaavat Window.requestAnimationFrame() ja VRDisplay.requestAnimationFrame() metodeihin — nämä alustavat normaalin ja WebVR-spesifisen renderöintisilmukan suorittamisen; niiden välisestä erosta selitetään hieman jäljempänä.
  • Muut muuttujat sisältävät viittauksia käyttöliittymän oikeassa alakulmassa näkyvän VR-sijainnin ja suuntauksen näyttävän tietolaatikon eri osiin.

VR-näytön hakeminen

Koodimme tärkeimpiä metodeja on start() — tämä suoritetaan, kun sivun body-osa on ladattu valmiiksi:

// start
//
// Called when the body has loaded is created to get the ball rolling.

document.body.onload = start;

Aluksistart() hakee webbisivumme - our HTML - <canvas> -osaan renderöitävään 3D-grafiikkaan tarvitun WebGL -ympäristön. Sitten tarkistetaan, että gl -ympäristö on käytettävissä — jos on, suoritetaan muutama metodi näytettävän skenen alustamiseksi.

function start() {
  canvas = document.getElementById("glcanvas");

  initWebGL(canvas);      // Initialize the GL context

  // WebGL setup code here

Seuraavaksi aloitetaan varsinainen näyttöprosessi. Siinä asetetaan canvas-elementti näyttämään selaimen koko näytettävä ala ja suorittamalla renderöintisilmukka(drawScene()) ensimmäisen kerran. Tässä siis ei-WebVR osuus— se normaali renderöintisilmukka.

    // draw the scene normally, without WebVR - for those who don't have it and want to see the scene in their browser

    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    drawScene();

Seuraavaksi tulee sitten ensimmäinen pala WebVR-koodia. Aluksi tarkistetaan, onko VR-näyttöjä edes käytettävissä Navigator.getVRDisplays  — tästä alkaa API:n käyttö ja tämä on hyvä paikka WebVR:n ominaisuuksien tarkistamiseen. Koodilohkon lopussa (else -osassa) näkyy, että ellei sopivia näyttöjä ole, näytetään viesti, ettei selain tue WebVR 1.1 :ää.

    // WebVR: Check to see if WebVR is supported
    if(navigator.getVRDisplays) {
      console.log('WebVR 1.1 supported');

if() { ... } koodilohkossa suoritetaan Navigator.getVRDisplays() metodi. Tämä palauttaa promise-olion, jonka sisältönä on lista tietokoneeseen kytketyistä VR-näytöistä. Se on tyhjä, ellei näyttöjä ole..

      // Then get the displays attached to the computer
      navigator.getVRDisplays().then(function(displays) {

Promise-olion then() -lohkossa tarkistetaan, että listan pituus on suurempi kuin 0; näin ollessa asetetaan vrDisplay -muuttujamme arvoksi listan ensimmäisen -indeksistä 0 löytyvän - alkion arvo. vrDisplay sisältää nyt VRDisplay olion, joka vastaa laitteeseen liitettyä näyttöä!

        // If a display is available, use it to present the scene
        if(displays.length > 0) {
          vrDisplay = displays[0];
          console.log('Display found');

Huom: On epätavallista, että tietokoneeseen olisi kytketty useita VR-näyttöjä, joten tätä yksinkertaista demoa varten usean näytön vaihtoehtoa ei huomioida.

VR-esityksen käynnistys ja pysäytys

Nyt kun käytössä on VRDisplay olio, sen avulla voidaan tehdä useita juttuja. Seuraavaksi haluamme käynnistää toiminnot WebGL-sisällön näyttämisen aloittamiseksi ja lopettamiseksi.

Jatkaaksemme edellisestä koodilohkosta, lisäämme käynnistys/pysäytys -painikkeeseemme (btn) tapahtumankuuntelijan (event listener) — ja painiketta klikattaessa halutaan tarkistaa, joko esitys näytölle on käynnissä (toteutus tälle on hieman kökkö ja perustuu painikkeen tekstin, textContent, tutkimiseen).

Ellei esitys näyttöön ole vielä käynnissä, käytetään VRDisplay.requestPresent() -metodia pyytämään selainta käynnistämään esitys näytölle. Parametrinä metodille annetaan lista VRLayerInit olioita, jotka vastaavat näytettäväksi haluttuja näyttötasoja.

Koska tällä hetkellä on mahdollista esittää vain yksi näyttötaso, ja ainoa vaadittu olion jäsen on VRLayerInit.source -ominaisuus (joka viittaa tuossa näyttötasossa näytettäväksi tarkoitettuun <canvas> :iin; annetaan muille parametreille järkevät oletusarvot — kts. leftBounds ja rightBounds)), parametri on yksinkertaisesti [{ source: canvas }].

requestPresent() palauttaa promise-olion, joka saa sisällön, kun esittäminen käynnistyy onnistuneesti.

          // Starting the presentation when the button is clicked: It can only be called in response to a user gesture
          btn.addEventListener('click', function() {
            if(btn.textContent === 'Start VR display') {
              vrDisplay.requestPresent([{ source: canvas }]).then(function() {
                console.log('Presenting to WebVR display');

Nyt kun esittämispyyntö oli ok, halutaan seuraavaksi asettaa renderöintisisältö esitettäväksi VR-näytölle. Aivan ensimmäiseksi asetetaan canvas samankokoiseksi VR-näytön näyttöalueen kanssa. Tämä onnistuu hakemalla VREyeParameters molemmille silmille käyttäen metodia VRDisplay.getEyeParameters().

Sen jälkeen lasketaan yksinkertaisesti VR-näytön kokonaisala silmän ominaisuuksien VREyeParameters.renderWidth ja VREyeParameters.renderHeight avulla.

                // Set the canvas size to the size of the vrDisplay viewport

                var leftEye = vrDisplay.getEyeParameters('left');
                var rightEye = vrDisplay.getEyeParameters('right');

                canvas.width = Math.max(leftEye.renderWidth, rightEye.renderWidth) * 2;
                canvas.height = Math.max(leftEye.renderHeight, rightEye.renderHeight);

Seuraavaksi pysäytetään renderöintisilmukka cancel the animation loop, joka aiemmin käynnistyi Window.requestAnimationFrame() kutsulla drawScene() -metodista ja sen sijaan kutsutaandrawVRScene():ä. Tämä metodi renderöi saman skenen kuin aiempikin käyttäen nyt VR-kohtaisia temppuja. Tämän renderöintisilmukan hallinta on nyt vastaavalla WebVR-versiolla, VRDisplay.requestAnimationFrame -metodilla.

                // stop the normal presentation, and start the vr presentation
                window.cancelAnimationFrame(normalSceneFrame);
                drawVRScene();

Lopuksi päivitetään painikkeen teksti, jolloin seuraavalla klikkauskerralla painike tuleekin pysäyttämään esityksen VR-näytöllä.

                btn.textContent = 'Exit VR display';
              });


VR-näytöllä esittämisen pysäyttämiseksi painikkeen seuraavalla klikkauksella kutsutaan VRDisplay.exitPresent() -metodia. Painikkeen teksti vaihdetaan taas toiseksi ja requestAnimationFrame -kutsut vaihdetaan taas keskenään. Tästä näkyy, että käytetään metodia VRDisplay.cancelAnimationFrame VR-renderöintisilmukan pysäyttämiseen ja normaalin skenen renderöinti käynnistyy drawScene()-metodilla.

            } else {
              vrDisplay.exitPresent();
              console.log('Stopped presenting to WebVR display');

              btn.textContent = 'Start VR display';

              // Stop the VR presentation, and start the normal presentation
              vrDisplay.cancelAnimationFrame(vrSceneFrame);
              drawScene();
            }
          });
        }
      });
    } else {
      console.log('WebVR API not supported by this browser.');
    }
  }
}

Kun esittäminen käynnistyy, selaimessa näkyy stereoskooppinen näkymä:

Seuraavasta opitaan, miten stereonäkymä varsinaisesti tehdään.

Miksi WebVR:llä on oma requestAnimationFrame()?

Tämä on hyvä kysymys. Perussyy on sulava renderöinti VR-näytössä, joka saadaan aikaan käyttämällä VR-näytön omaa näytönpäivitysnopeutta eikä tietokoneen. VR-näytön päivitysnopeudet ovat tietokonetta suurempia, yleisesti jopa  90fps. Tämä poikkeaa tietokoneen peruspäivitysnopeudesta.

Huomaa, että kun VR-näytössä ei esitetä, VRDisplay.requestAnimationFrame toimii identtisesti Window.requestAnimationFrame:n kanssa, joten halutessasi voisit käyttää vain yhtä renderöintisilmukkaa tekemämme sovelluksen kahden silmukan sijaan. Sovelluksessa käytetään kahta, koska VR-esityksen ollessa päällä halutaan tehdä hieman eri asioita kuin ilman sitä, ja nämä halutaan selkeyden vuoksi erottaa.

Renderöinti ja näyttäminen

Tässä vaiheessa on nähty kaikki koodi, mikä tarvitaan VR-laitteiston hakemiseen, skenen näyttöpyynnön lähettämiseen ja renderöintisilmukan käynnistämiseen. Seuraavaksi kurkataan renderöintisilmukan sisälle ja selitetään, miten sen WebVR-spesifiset osat toimivat.

Aluksi tarkastellaan renderöintisilmukkametodin  — drawVRScene() määrittelyä. Ensimmäinen tehtävä on kutsua VRDisplay.requestAnimationFrame() -metodia silmukan toiston jatkamiseksi ensimmäisen kutsukerran jälkeen (tämä tehtiin aiemmin koodissa, kun VR-näytölle esittäminen aloitettiin). Tämä metodikutsu asetetaan globaalin vrSceneFrame -muuttujan arvoksi, jotta silmukka saadaan keskeytettyä VRDisplay.cancelAnimationFrame() -metodilla, kun VR-esitys loppuu.

function drawVRScene() {
  // WebVR: Request the next frame of the animation
  vrSceneFrame = vrDisplay.requestAnimationFrame(drawVRScene);

Seuraavaksi kutsutaan metodia VRDisplay.getFrameData(), joka saa parametriksi muuttujanimen, johon ruudun tiedot halutaan. Tämähän alustettiin jo aiemmin nimellä  frameData. Metodin suorittamisen jälkeen tässä muuttujassa on tarpeelliset tiedot seuraavan ruudun renderöintiin VR -laitteelle pakattuna VRFrameData -olioon. Mukana on tieto projektio- ja näkymämatriiseista, joiden avulla skene saadaan renderöityä oikein vasemmalle ja oikealle silmälle sekä ajantasainen VRPose -olio, jossa on mm. VR-näytön suunta- ja sijaintitiedot.

Tätä tulee kutsua joka ruudun kohdalla, jotta renderöity näkymä olisi ajantasainen.

  // Populate frameData with the data of the next frame to display
  vrDisplay.getFrameData(frameData);

Seuraavaksi haetaan senhetkinen VRPose ominaisuudesta VRFrameData.pose, tallennetaan sijainti ja suunta myöhempää käyttöä varten ja lähetetään pose-tieto näytettäväksi sivun tilatietoruutuun, siis mikäli poseStatsDisplayed -muuttuja on saanut arvon true.

  // You can get the position, orientation, etc. of the display from the current frame's pose

  var curFramePose = frameData.pose;
  var curPos = curFramePose.position;
  var curOrient = curFramePose.orientation;
  if(poseStatsDisplayed) {
    displayPoseStats(curFramePose);
  }

  Seuraavaksi canvas:in sisältö tyhjennetään ennen uuden piirron aloittamista, jotta seuraava ruutu piirrettäisiin puhtaalle pohjalle, eikä aiempi ruutu olisi alla sotkemassa:

  // Clear the canvas before we start drawing on it.

  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

Nyt renderöidään molempien silmien näkymä. Aluksi tarvitaan projektion ja näkymän sijainti renderöintiä varten. Nämä ovat WebGLUniformLocation -olioita, jotka on luotu WebGLRenderingContext.getUniformLocation() -metodilla käyttäen parametreinä shader-ohjelman tunnusta ja nimitunnistetta.

  // WebVR: Create the required projection and view matrix locations needed
  // for passing into the uniformMatrix4fv methods below

  var projectionMatrixLocation = gl.getUniformLocation(shaderProgram, "projMatrix");
  var viewMatrixLocation = gl.getUniformLocation(shaderProgram, "viewMatrix");

Seuraava renderöintivaihe sisältää:

  • Viewportin koon määrittäminen vasemmalle silmälle  WebGLRenderingContext.viewport -metodilla — tämä on tietenkin canvas:in leveyden ensimmäinen puolikas kertaa sen täysi korkeus.
  • Vasemmalle silmälle renderöintiin käytettävät näkymä- ja projektiomatriisien arvojen määrittäminen — tämä tehdään käyttämällä WebGLRenderingContext.uniformMatrix4fv -metodia, joka saa parametrikseen yllä haetut sijaintitiedot ja VRFrameData -oliolta saatavat vasemman puolen matriisit.
  • drawGeometry() funktion suorittaminen, joka suorittaa varsinaisen skenen renderöinnin — ja edellisistä vaiheista johtuen siis vain vasemmalle silmälle.
  // WebVR: Render the left eye’s view to the left half of the canvas
  gl.viewport(0, 0, canvas.width * 0.5, canvas.height);
  gl.uniformMatrix4fv(projectionMatrixLocation, false, frameData.leftProjectionMatrix);
  gl.uniformMatrix4fv(viewMatrixLocation, false, frameData.leftViewMatrix);
  drawGeometry();

Ja sama oikealle silmälle:

  // WebVR: Render the right eye’s view to the right half of the canvas
  gl.viewport(canvas.width * 0.5, 0, canvas.width * 0.5, canvas.height);
  gl.uniformMatrix4fv(projectionMatrixLocation, false, frameData.rightProjectionMatrix);
  gl.uniformMatrix4fv(viewMatrixLocation, false, frameData.rightViewMatrix);
  drawGeometry();

Seuraavaksi määritelläändrawGeometry() funktio. Suurin osa siitä koostuu tavallisesta WebGL -koodista, jolla saadaan piirrettyä 3D-kuutio. WebVR-spesifisiä osia löytyy mvTranslate() jamvRotate() funktiokutsuista — ne välittävät matriisit WebGL-ohjelmalle, joka määrittää sen hetkiselle ruudulle kuution sijainnin ja kierron.

Kuten huomaat, näitä arvoja muokataan VRPose -oliolta saaduilla VR-näytön sijainti- (curPos) ja kiertotiedoilla (curOrient). Sen seurauksena esimerkiksi päätä vasemmalle käännettäessä kuvassa näkyvä kuutio siirtyy aivan odotetustikin oikealle, kun  x-sijaintitieto (curPos[0]) ja y-kiertotieto ([curOrient[1]) lisätään x-translaatioarvoon.

Tämä on 'quick and dirty' -tapa käyttää VR pose-tietoa, mutta se näyttänee kuitenkin perusidean.

  function drawGeometry() {
    // Establish the perspective with which we want to view the
    // scene. Our field of view is 45 degrees, with a width/height
    // ratio of 640:480, and we only want to see objects between 0.1 units
    // and 100 units away from the camera.

    perspectiveMatrix = makePerspective(45, 640.0/480.0, 0.1, 100.0);

    // Set the drawing position to the "identity" point, which is
    // the center of the scene.

    loadIdentity();

    // Now move the drawing position a bit to where we want to start
    // drawing the cube.

    mvTranslate([
                  0.0 - (curPos[0] * 25) + (curOrient[1] * 25),
                  5.0 - (curPos[1] * 25) - (curOrient[0] * 25),
                  -15.0 - (curPos[2] * 25)
               ]);

    // Save the current matrix, then rotate before we draw.

    mvPushMatrix();
    mvRotate(cubeRotation, [0.25, 0, 0.25 - curOrient[2] * 0.5]);

    // Draw the cube by binding the array buffer to the cube's vertices
    // array, setting attributes, and pushing it to GL.

    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesBuffer);
    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);

    // Set the texture coordinates attribute for the vertices.

    gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesTextureCoordBuffer);
    gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);

    // Specify the texture to map onto the faces.

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, cubeTexture);
    gl.uniform1i(gl.getUniformLocation(shaderProgram, "uSampler"), 0);

    // Draw the cube.

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
    setMatrixUniforms();
    gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);

    // Restore the original matrix

    mvPopMatrix();
  }

Seuraava koodipalanen ei liity mitenkään WebVR:ään — siinä vain kierretään kuutiota joka ruudun osalta:

  // Update the rotation for the next draw, if it's time to do so.

  var currentTime = (new Date).getTime();
  if (lastCubeUpdateTime) {
    var delta = currentTime - lastCubeUpdateTime;

    cubeRotation += (30 * delta) / 1000.0;
  }

  lastCubeUpdateTime = currentTime;

Renderöintisilmukan viimeiseen osaan kuuluu VRDisplay.submitFrame() -metodin kutsuminen — kaikki tarpeellinen on nyt tehty ja näyttö on renderöity <canvas> :iin, tämä metodi sitten toimittaa ruudun VR-näytölle, jolloin se ruutu näkyy myös siinä.

  // WebVR: Indicate that we are ready to present the rendered frame to the VR display
  vrDisplay.submitFrame();
}

Pose (sijainti, kierto, ym.) -tiedon näyttäminen

Tässä osassa tutustutaan displayPoseStats() -funktioon, joka näyttää kunkin ruudun päivitetyt pose-tiedot. Kyseinen funktio on melko yksinkertainen.

Aluksi tallennetaan VRPose-oliolta saadut kuusi ominaisuutta omiin muuttujiin — ne ovat tyyppiä Float32Array.

function displayPoseStats(pose) {
  var pos = pose.position;
  var orient = pose.orientation;
  var linVel = pose.linearVelocity;
  var linAcc = pose.linearAcceleration;
  var angVel = pose.angularVelocity;
  var angAcc = pose.angularAcceleration;

Sitten tiedot kirjoitetaan tietolaatikkoon ja päivitetään ne joka ruudun kohdalla. Arvot on pyöristetty toFixed() -metodilla luettavuuden vuoksi.

Huomaa ehtolause lineaarisen ja kulmakiihtyvyyden vektorien arvojen tarkastamisessa - siinä varmistetaan ennen näyttämistä, että arvot on tosiaan saatu luettua. Useimmilta VR-laitteistolta näitä arvoja ei vielä saada, joten ilman tarkistamista seuraisi virhetoiminta (ellei arvoja saada, vektorien arvoksi tulee null).

  posStats.textContent = 'Position: x ' + pos[0].toFixed(3) + ', y ' + pos[1].toFixed(3) + ', z ' + pos[2].toFixed(3);
  orientStats.textContent = 'Orientation: x ' + orient[0].toFixed(3) + ', y ' + orient[1].toFixed(3) + ', z ' + orient[2].toFixed(3);
  linVelStats.textContent = 'Linear velocity: x ' + linVel[0].toFixed(3) + ', y ' + linVel[1].toFixed(3) + ', z ' + linVel[2].toFixed(3);
  angVelStats.textContent = 'Angular velocity: x ' + angVel[0].toFixed(3) + ', y ' + angVel[1].toFixed(3) + ', z ' + angVel[2].toFixed(3);

  if(linAcc) {
    linAccStats.textContent = 'Linear acceleration: x ' + linAcc[0].toFixed(3) + ', y ' + linAcc[1].toFixed(3) + ', z ' + linAcc[2].toFixed(3);
  } else {
    linAccStats.textContent = 'Linear acceleration not reported';
  }

  if(angAcc) {
    angAccStats.textContent = 'Angular acceleration: x ' + angAcc[0].toFixed(3) + ', y ' + angAcc[1].toFixed(3) + ', z ' + angAcc[2].toFixed(3);
  } else {
    angAccStats.textContent = 'Angular acceleration not reported';
  }
}

WebVR -tapahtumat

The WebVR spesifikaatiossa on määritetty useita liipaistavia tapahtumia (event), ja näin koodilla voidaan reagoida VR-näytön tilan muutoksiin (vrt. Window events). Esimerkiksi:

Demossa on seuraava esimerkki tapahtumista:

window.addEventListener('vrdisplaypresentchange', function(e) {
  console.log('Display ' + e.display.displayId + ' presentation has changed. Reason given: ' + e.reason + '.');
});

Kuten näet event object tarjoaa kaksi hyödyllistä ominaisuutta — VRDisplayEvent.display, joka viittaa VRDisplay tapahtuman tuottajaan, ja VRDisplayEvent.reason, jossa on selkokielinen syy tapahtumaan.

Tämä on hyvin käyttökelpoinen tapahtuma; sitä voidaan käyttää huomaan yllättävä näytön irrotus, joka estäää tarpeettomat virheviestit ja kertoo tilanteen käyttäjälle. Googlen Webvr.info -esitysdemossa tapahtumaa käytetään suorittamaan onVRPresentChange() funktio, joka päivittää käyttöliittymän kontrollit tilannetta vastaaviksi ja muuttaa canvasin kokoa.

Yhteenveto

Tässä artikkelissa kerrottiin hyvin yksinkertaisen WebVR 1.1 sovelluksen tekemisestä, jonka avulla pääset alkuun sovellusten kehittämisessä.

Document Tags and Contributors

 Contributors to this page: laitinent
 Last updated by: laitinent,