VR panorama browser
Zoals ik afgelopen week al schreef, wilde ik de panorama-viewer verder uitbreiden om meer foto’s toe te voegen. Interacties in de derde dimensie werken echter nét anders dan op het platte scherm. Daarnaast zijn allerlei conventies nog helemaal niet uitgewerkt, dus iedereen doet maar wat en dat is heel verfrissend.
In de 20e eeuw werden de nieuwe grafische interfaces aangeleerd door het gebruik van bedieningselementen die waren ontworpen naar het voorbeeld van een fysieke tegenhanger, een skeuomorfisme zoals dat heet. Mappen, schuifknoppen en zandlopers; allemaal elementen uit de echte wereld om ons te laten begrijpen hoe de interface werkt in de platte digitale wereld.
Meta Quest: Zwevende 2D windows met een 3D sausje
Digitale 3D werelden kunnen werken op een heel andere manier, maar de interface-ontwerpers maken het zich er makkelijk vanaf en plakken gewoon een 2D interface in de lucht, want die kennen we al. Ze willen het ons nu nog niet te lastig maken, maar de échte revolutie moet nog komen, denk ik.
Apple visionOS: Nog niet veel beter
Simpel
Hoe dan ook, ik wilde iets simpels maken om mee te beginnen. Met A-Frame doe je dat met Custom Elements in HTML. Hieronder zie je het specifieke deel om de scene te definiëren.
<a-scene>
<a-assets>
<img id="image-0" src="image-0.jpg">
<img id="city" src="https://cdn.aframe.io/a-painter/images/sky.jpg">
<img id="floor" src="https://cdn.aframe.io/a-painter/images/floor.jpg">
</a-assets>
<a-sky src="#city"></a-sky>
<a-curvedimage id="panorama" src="#image-0"
position="0 2 0" height="2.5" radius="2"
theta-start="60" theta-length="240"></a-curvedimage>
<a-cylinder id="ground" src="#floor" radius="32" height="0.1"></a-cylinder>
</a-scene>
Eerst definieer je een aantal assets, in dit geval afbeeldingen, waar je vanaf andere plekken naar kan verwijzen. Om te
voorkomen dat je in het luchtledige lijkt te zweven is het verstandig een a-sky
toe te voegen met een 360º afbeelding.
Daarnaast heb ik een a-cylinder
toegevoegd die als een soort vloer dient.
De a-curvedimage
bevat het echte panorama-plaatje en is eigenlijk een boogsegment van de wand van een cilinder. Het is
een beetje zoeken naar de juiste waardes, maar de meeste van mijn panorama’s zijn ongeveer 240º. Als het niet helemaal
klopt, is dat nog niet zo’n ramp, want dat zie je amper, behalve als je met veel rechte lijnen werkt en het allemaal
precies zou moet passen.
Nu voeg ik nog twee a-image
toe onder de panorama om zometeen vooruit en achteruit te kunnen en voila, de scène is
zo’n beetje klaar:
Overzicht van de scene
Met A-Frame hoef je je om de rendering verder geen zorgen meer te maken. Je headset schakelt om naar VR-modus en je
wordt omringd door de scène die je hebt gebouwd. De interactie daarentegen zul je wel zelf moeten opbouwen, want anders
dan op het platte web kan je hier niet gewoon ergens een <a href=...>
wegzetten om een link te maken.
Interactie
In 2D interfaces zijn we gewend dat we één aanwijzer hebben die we eventueel met meerdere apparaten kunnen bedienen ( muis, touchpad, tekenpen, …). In de 3D wereld zijn al die apparaten opeens onafhankelijke bedieningen geworden, vergelijkbaar met hoe een smartphone elke vinger apart detecteert en “multitouch gestures” herkent. A-Frame ondersteunt hoofd- en controller-tracking, dus je kijkrichting en wat je met je controllers doet kan als invoer dienen. Omdat je hoofd (waarschijnlijk) geen knoppen heeft, werkt een interactie daarmee anders dan met een hand-controller.
Een controller declareer je door een a-entity
te maken met een aantal attributen, bijvoorbeeld zo:
<a-entity oculus-touch-controls="hand: right"
laser-controls
b-button-listener></a-entity>
Met oculus-touch-controls="hand: right"
zeg je dat je de Meta Quest controller voor de rechter hand wil configureren.
De laser-controls
zorgt ervoor dat de controller een laserstraal afschiet in de wijsrichting, en dat een aantal events
worden afgevuurd als die laserstraal een object raakt, waarover later meer.
Uit de VR-modus gaan
Ten slotte koppel ik met b-button-listener
mijn eigen code aan de controller hardware:
AFRAME.registerComponent('b-button-listener', {
init: function () {
this.el.addEventListener('bbuttondown', function (e) {
const sceneEl = document.querySelector('a-scene');
if (sceneEl.is('vr-mode')) {
sceneEl.exitVR();
}
});
}
});
Dit zorgt ervoor dat als je op de B knop op de controller drukt wanneer je in VR-mode bent, dat je uit VR-mode gaat.
Een foto vooruit of achteruit gaan
De twee kleine fotootjes onderaan op het screenshot had ik nog niet aan de scène toegevoegd, dus dat doen we nog even:
<a-image id="prev-image" src="#image-2"
position="-1 0.5 -1.5" rotation="-45 30 0"
width="1" height="0.33"
cursor-listener="direction: prev"></a-image>
<a-image id="next-image" src="#image-1"
position="1 0.5 -1.5" rotation="-45 -30 0"
width="1" height="0.33"
cursor-listener="direction: next"></a-image>
Hier zie je de cursor-listener
component. Deze code is straks verantwoordelijk voor het naar het click
signaal
luisteren dat de laser-controls
component produceert wanneer je op een van de a-image
s “klikt”. Je ziet dat je extra
informatie kan meegeven, net als bij de oculus-touch-controls
, om de component te configureren.
AFRAME.registerComponent('cursor-listener', {
schema: {
direction: {type: 'string', default: 'next'}
},
init: function () {
this.el.addEventListener('click', (e) => {
switch (this.data.direction) {
case 'prev':
nextImage(-1);
break;
default:
nextImage(1);
break;
}
});
}
});
In de code hierboven wordt aan this.el
, dat is de a-image
waar het op staat, een event listener toegevoegd voor
het click
signaal. Afhankelijk van de waarde van direction
zal hij nu de volgende of de vorige afbeelding inladen.
De logica voor het wisselen van de afbeelding is niet A-Frame of WebXR specifiek en kan je vinden in de source van de panorama pagina (net als de rest van deze blog trouwens).
En dat is het! Het resultaat is een wereld waarin je kan schakelen tussen zes panorama’s met behulp van je controllers! Voor degenen zonder headset, een filmpje:
Nuttige links
- Een lijst van voorbeelden met A-Frame (in onwijze 90s homepage vibe) van Lee Stemkoski
- A-Frame documentatie
Webmentions
Heb je een reactie op dit artikel geschreven? Stuur me een webmention! Het kan een paar dagen duren voordat je reactie hier verschijnt.