WebVR Teil 5: Design und Implementierung
Veröffentlicht: 2022-03-11Ich liebe es, Projekte „fertig“ zu machen. Wir sind am Ende unserer Reise angelangt – und der Geburt unserer Himmelsgravitationssimulation in WebVR.
In diesem letzten Beitrag werden wir unseren Hochleistungssimulationscode (Artikel 1, 2, 3) in einen WebVR-Visualizer stecken, der auf dem Canvas-Visualizer (Artikel 4) basiert.
- „n-Körper-Problem“ Intro und Architektur
- Web Worker erhalten uns zusätzliche Browser-Threads
- WebAssembly und AssemblyScript für unseren O(n²)-Leistungsengpasscode
- Canvas-Datenvisualisierung
- WebVR-Datenvisualisierung
Dies ist ein längerer Artikel, daher überspringen wir einige zuvor behandelte technische Details. Schauen Sie sich die vorherigen Beiträge an, wenn Sie eine Orientierung wünschen, oder lesen Sie gefährlich weiter.
Wir haben den Paradigmenwechsel des Browsers von einer Singlethread-JavaScript-Laufzeit zu einer Multithread-Hochleistungslaufzeit (Web-Worker) (WebAssembly) untersucht. Diese leistungsstarken Desktop-Computing-Funktionen sind in Progressive Web Apps und dem SaaS-Verteilungsmodell verfügbar.
VR wird überzeugende, ablenkungsfreie Verkaufs- und Marketingumgebungen schaffen, um zu kommunizieren, zu überzeugen und Engagement zu messen (Eye-Tracking und Interaktion). Daten werden immer noch Nullen und Einsen sein, aber die erwartete Zusammenfassung und das Verbrauchererlebnis werden WebVR sein – genau wie wir heute mobile Dashboard-Erlebnisse für das flache Web erstellen.
Diese Technologien ermöglichen auch verteiltes Browser-Edge-Computing. Beispielsweise könnten wir eine webbasierte Anwendung erstellen, um unsere WebAssembly-Berechnungen für Millionen von Sternen in einer Simulation auszuführen. Ein weiteres Beispiel ist eine Animationsanwendung, die die Kreationen anderer Benutzer rendert, während Sie Ihre eigenen bearbeiten.
Unterhaltungsinhalte führen die Einführung von Virtual Reality an, genau wie Unterhaltung auf Mobilgeräten. Sobald VR jedoch normal ist (wie es heute das Mobile-First-Design ist), wird es die erwartete Erfahrung sein (VR-First-Design). Dies ist eine sehr aufregende Zeit für Designer und Entwickler – und VR ist ein völlig anderes Designparadigma.
Sie sind kein VR-Designer, wenn Sie nicht greifen können. Das ist eine mutige Aussage, und heute ist der tiefe Einblick in das VR-Design. Dieses Feld wird gerade erfunden, während Sie dies lesen. Mein Ziel ist es, meine Erfahrungen mit Software und Film zu teilen, um das Gespräch über das „VR-First-Design“ anzuregen. Wir lernen alle voneinander.
Angesichts dieser grandiosen Vorhersagen wollte ich dieses Projekt als professionelle Tech-Demo abschließen – WebVR ist dafür eine großartige Wahl!
WebVR und Google A-Frame
Das WebVR-Git-Repo ist aus mehreren Gründen ein Fork der Canvas-Version. Es macht das Hosten des Projekts auf Github-Seiten einfacher, und WebVR erforderte ein paar Änderungen, die die Canvas-Version und diese Artikel überladen hätten.
Wenn Sie sich an unseren ersten Beitrag zur Architektur erinnern, haben wir die gesamte Simulation an nBodySimulator
.
Der Webworker-Beitrag zeigte, dass nBodySimulator
eine step()
Funktion hat, die alle 33 ms der Simulation aufgerufen wird. step()
ruft calculateForces()
auf, um unseren O(n²) WebAssembly-Simulationscode (Artikel 3) auszuführen, aktualisiert dann die Positionen und zeichnet neu. In unserem vorherigen Beitrag zum Erstellen einer Canvas-Visualisierung haben wir dies mit einem Canvas-Element implementiert, ausgehend von dieser Basisklasse:
/** * Base class that console.log()s the simulation state. */ export class nBodyVisualizer { constructor(htmlElement) { this.htmlElement = htmlElement this.resize() this.scaleSize = 25 // divided into bodies drawSize. drawSize is log10(mass) // This could be refactored to the child class. // Art is never finished. It must be abandoned. } resize() {} paint(bodies) { console.log(JSON.stringify(bodies, null, 2)) } }
Definieren Sie die Integrationsherausforderung
Wir haben die Simulation. Jetzt wollen wir uns in WebVR integrieren – ohne unser Projekt neu zu gestalten. Alle Anpassungen, die wir an der Simulation vornehmen, erfolgen alle 33 ms im Haupt-UI-Thread in der Funktion paint(bodies)
.
So werden wir „erledigt“ messen. Ich bin gespannt – ran an die Arbeit!
Wie man eine virtuelle Realität macht
Zuerst brauchen wir ein Design:
- Woraus besteht VR?
- Wie drückt sich WebVR-Design aus?
- Wie können wir damit interagieren ?
Virtual Reality reicht bis in die Anfänge der Zeit zurück. Jede Lagerfeuergeschichte ist eine winzige virtuelle Welt aus absonderlichen Übertreibungen, die von trivialen Details übertüncht wird.
Wir können unsere Lagerfeuergeschichte verzehnfachen, indem wir stereoskopische 3D-Visuals und Audio hinzufügen. Mein Dozent für Budgetierung der Filmproduktion sagte immer: „Wir zahlen nur für das Poster. Wir bauen keine Realität.“
Wenn Sie mit dem Browser-DOM vertraut sind, wissen Sie, dass es eine baumartige hierarchische Struktur erstellt.
Implizit im Design des Webs ist der Betrachter von „vorne“. Ein Blick von der Seite würde die DOM-Elemente als Linien enthüllen, und von hinten würden wir nur das Tag <body>
sehen, weil es seine untergeordneten Elemente verdeckt.
Ein Teil der immersiven Erfahrung von VR besteht darin, dass der Benutzer seinen Standpunkt, Stil, Tempo und die Reihenfolge der Interaktionen steuern kann. Dabei müssen sie nichts Besonderes beachten. Wenn Sie die Kamera programmatisch bewegen oder drehen, kotzen sie buchstäblich vor VR-Krankheit.
Bitte beachten Sie, dass VR-Krankheit kein Scherz ist. Sowohl unsere Augen als auch unsere Innenohren erkennen Bewegungen. Es ist sehr wichtig für ein Tier, das aufrecht geht. Wenn diese Bewegungssensoren nicht übereinstimmen, geht unser Gehirn natürlich davon aus, dass unser Mund wieder Unsinn gegessen hat, und erbricht sich. Wir waren alle einmal Kinder. Über diesen Überlebensinstinkt in VR wurde bereits viel geschrieben. Der Titel „Epic Fun“ ist kostenlos auf Steam erhältlich und die Achterbahn ist die beste VR-Krankheitsdemo, die ich gefunden habe.
Virtuelle Realität wird als „Szenengraph“ ausgedrückt. Ein Szenendiagramm hat das gleiche baumartige Muster wie das DOM, um die Details und die Komplexität einer überzeugenden 3D-Umgebung zu verbergen. Anstatt zu scrollen und zu routen, positionieren wir den Betrachter jedoch dort, wo er das Erlebnis zu sich ziehen möchte.
Hier ist das Hello World-Szenendiagramm aus Googles A-Frame WebVR Framework:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello, WebVR! • A-Frame</title> <meta name="description" content="Hello, WebVR! • A-Frame"> <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script> </head> <body> <a-scene background="color: #FAFAFA"> <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9" shadow></a-box> <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E" shadow></a-sphere> <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D" shadow></a-cylinder> <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" shadow></a-plane> </a-scene> </body> </html>
Dieses HTML-Dokument erstellt ein DOM im Browser. Die <a-*>
Tags sind Teil des A-Frame-Frameworks, und <a-scene>
ist die Wurzel des Szenendiagramms. Hier sehen wir vier 3D-Primitive, die in der Szene angezeigt werden.
Beachten Sie zunächst, dass wir die Szene in einem flachen Webbrowser anzeigen. Die kleine Maske unten rechts lädt den Benutzer ein, in einen stereoskopischen 3D-Modus zu wechseln.
Theoretisch sollten Sie in der Lage sein:
- Öffnen Sie diese auf Ihrem Telefon
- Halten Sie Ihr Telefon an Ihr Gesicht
- Erfreuen Sie sich an der Pracht einer neuen Realität!
Ich habe das nie ohne die ausgefallenen Linsen eines VR-Headsets zum Laufen gebracht. Sie können ein VR-Headset für ein Android-Telefon günstig bekommen (ein einfaches Gerät, das auf Google Cardboard basiert), aber für die Entwicklung von Inhalten empfehle ich ein eigenständiges HMD (Head Mounted Display) wie Oculus Quest.
Ähnlich wie Tauchen oder Fallschirmspringen ist Virtual Reality ein Ausrüstungssport.
VR-Designer-Lernprogramm „Cliff“
Beachten Sie, dass die A-Frame-Hello-World-Szene eine Standardbeleuchtung und -kamera hat:
- Die Flächen des Würfels haben unterschiedliche Farben - der Würfel ist selbstschattend.
- Der Würfel wirft einen Schatten auf die Ebene - es gibt ein gerichtetes Licht.
- Es gibt keine Lücke zwischen dem Würfel und dem Flugzeug - dies ist eine Welt mit Schwerkraft.
Dies sind kritische Hinweise, die dem Betrachter sagen: „Entspann dich, dieses Ding in deinem Gesicht ist völlig normal.“
Beachten Sie auch, dass diese Standardeinstellung im obigen Code der Hello World-Szene enthalten ist. A-Frame bietet klugerweise einen vernünftigen Standard, aber beachten Sie - Kamera und Beleuchtung sind die Kluft, die Flat-Web-Designer überqueren müssen, um VR zu erstellen.
Wir nehmen die Standard-Beleuchtungseinstellung als selbstverständlich hin. Zum Beispiel Schaltflächen:
Beachten Sie, wie allgegenwärtig diese implizite Beleuchtung in Design und Fotografie ist. Sogar die Schaltfläche „Flaches Design“ konnte sich der Standardbeleuchtung des Webs nicht entziehen – sie wirft einen Schatten nach unten und nach rechts.
Das Entwerfen, Kommunizieren und Implementieren von Beleuchtungs- und Kamera-Setups sind die Lernklippe des WebVR-Designers. Die „Sprache des Films“ ist eine Sammlung kultureller Normen – ausgedrückt in unterschiedlichen Kamera- und Lichteinstellungen – die dem Publikum die Geschichte emotional vermitteln. Die Filmprofis, die Lichter und Kamera um eine Szene herum entwerfen/bewegen, sind die Grip-Abteilung.
Zurück zu unserer virtuellen Realität
Nun denn, lass uns wieder an die Arbeit gehen. Unsere himmlische WebVR-Szene hat ein ähnliches Muster:
<!DOCTYPE> <html> <head> <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script> <script src="https://unpkg.com/[email protected]/dist/aframe-event-set-component.min.js"></script> <script src="main.js"></script> </head> <body> <a-scene> <a-sky color="#222"></a-sky> <a-entity geometry="primitive: circle; radius: 12" position="0 0 -.5" material="color: #333; transparent: true; opacity: 0.5"> <a-sphere color="black" radius=."02"></a-sphere> </a-entity> <a-entity></a-entity> <a-entity geometry="primitive: plane; width: 2; height: auto" position="0 -10 .3" rotation="55 0 0" material="color: blue" text="value: Welcome Astronaut!..."> </a-entity> <a-entity position="0 -12 .7" rotation="55 0 0"> <a-camera> <a-cursor color="#4CC3D9" fuse="true" timeout="1"></a-cursor> </a-camera> </a-entity> </a-scene> </body> </html>
Dieses HTML-Dokument lädt das A-Frame-Framework und ein Interaktions-Plugin. Unsere Szene beginnt bei <a-scene>
.
Im Inneren beginnen wir mit einem <a-sky color="#222"></a-sky>
-Element, um alles, was wir nicht in der Szene definieren, mit Hintergrundfarbe zu versehen.
Als Nächstes erstellen wir ein „Orbitalflugzeug“, an dem sich der Betrachter „festhalten“ kann, während er durch unsere seltsame und unbekannte Welt fliegt. Wir erstellen dies als Scheibe und eine kleine schwarze Kugel bei (0,0,0). Ohne dies fühlte sich das Drehen für mich „unbegründet“ an:
<a-entity geometry="primitive: circle; radius: 12" position="0 0 -.5" material="color: #333; transparent: true; opacity: 0.5"> <a-sphere color="black" radius=."02"></a-sphere> </a-entity>
Als nächstes definieren wir eine Sammlung, in der wir A-Frame-Entitäten hinzufügen/entfernen/neu positionieren können.
<a-entity></a-entity>
Dies ist die Freigabe für die paint(bodies)
von nBodyVisualizer
, um ihre Arbeit zu erledigen.
Dann stellen wir die Beziehung zwischen dem Betrachter und dieser Welt her. Als Tech-Demo soll diese Welt den Betrachter WebVR und die Browser-Technologie, die es ermöglicht, erkunden lassen. Eine einfache „Astronauten“-Erzählung schafft ein spielerisches Gefühl, und dieser stellare Wegweiser ist ein weiterer Bezugspunkt für die Navigation.
<a-entity geometry="primitive: plane; width: 2; height: auto" position="0 -10 .3" rotation="55 0 0" material="color: blue" text="value: Welcome Astronaut!\n ..."> </a-entity>
Das vervollständigt unseren Szenengraphen. Schließlich wollte ich eine Art Interaktion auf einer Telefondemo zwischen dem Benutzer und dieser Spinnwelt. Wie können wir die Schaltfläche „Schrott werfen“ in VR nachbilden?
Der Button ist ein elementares Element allen modernen Designs – wo sind die VR-Buttons?
Interaktionen in WebVR
Virtual Reality hat sein eigenes „above“ und „below the fold“. Die erste Interaktion eines Zuschauers erfolgt über seinen Avatar oder seine Kamera. Dies sind alle Steuerelemente zum Herumzoomen.
Wenn Sie dies auf einem Desktop lesen, können Sie mit WASD die Kamera bewegen und mit der Maus drehen. Diese Erkundung enthüllt Informationen, drückt aber nicht Ihren Willen aus.
Real Reality hat ein paar sehr wichtige Funktionen, die nicht oft im Internet zu finden sind:
- Perspektive - Objekte werden sichtbar kleiner, wenn sie sich von uns entfernen.
- Okklusion – Objekte werden basierend auf der Position versteckt und aufgedeckt.
VR simuliert diese Funktionen, um den 3D-Effekt zu erzeugen. Sie können auch in VR verwendet werden, um Informationen und Schnittstellen anzuzeigen – und um die Stimmung vor der Präsentation der Interaktionen festzulegen. Ich habe festgestellt, dass die meisten Leute nur eine Minute brauchen, um die Erfahrung zu genießen, bevor sie weitermachen.

In WebVR interagieren wir im 3D-Raum. Dafür haben wir zwei grundlegende Werkzeuge:
- Kollision – ein passives 3D-Ereignis, das ausgelöst wird, wenn zwei Objekte denselben Raum teilen.
- Projektion - ein aktiver 2D-Funktionsaufruf, der alle Objekte auflistet, die eine Linie schneiden.
Kollision ist die „VR-ähnlichste“ Interaktion
In VR ist eine „Kollision“ genau das, wonach es sich anhört: Wenn zwei Objekte denselben Raum teilen, erzeugt A-Frame ein Ereignis.
Damit der Benutzer einen Knopf „drücken“ kann, müssen wir ihm eine Spielfigur und etwas geben, womit er den Knopf drücken kann.
Leider kann WebVR noch keine Controller übernehmen – viele Leute werden sich eine Flat-Web-Version auf ihrem Desktop oder Telefon ansehen, und viele werden ein Headset wie Google Cardboard oder Samsungs Gear VR verwenden, um eine stereoskopische Version zu zeigen.
Wenn der Benutzer keine Controller hat, kann er keine Dinge ausstrecken und „berühren“, sodass jede Kollision mit seinem „persönlichen Bereich“ stattfinden muss.
Wir könnten dem Spieler eine astronautenförmige Figur geben, mit der er sich bewegen kann, aber den Benutzer in ein wirbelndes Miasma von Planeten zu zwingen, scheint ein wenig abstoßend und steht im Widerspruch zu der Geräumigkeit unseres Designs.
Projektion ist ein „webähnlicher“ 2D-Klick in einem 3D-Raum
Neben „Kollision“ können wir auch „Projektion“ verwenden. Wir können eine Linie durch unsere Szene projizieren und sehen, was sie berührt. Das bekannteste Beispiel ist der „Teleportstrahl“.
Ein Teleportstrahl zeichnet eine Linie in der Welt nach, um anzuzeigen, wohin sich ein Spieler bewegen kann. Diese „Projektion“ sucht nach Landeplätzen. Es gibt ein oder mehrere Objekte im Pfad der Projektion zurück. Hier ist ein Beispiel für einen Teleportstrahl:
Beachten Sie, dass der Strahl tatsächlich als Parabel implementiert ist, die nach unten zeigt. Dies bedeutet, dass es wie ein geworfenes Objekt auf natürliche Weise mit dem „Boden“ kreuzt. Dies legt natürlich auch eine maximale Teleportationsentfernung fest. Limits sind die wichtigsten Designentscheidungen in VR. Glücklicherweise hat die Realität viele natürliche Einschränkungen.
Die Projektion "flacht" die 3D-Welt in 2D ab, sodass Sie auf Dinge zeigen können, um sie wie eine Maus anzuklicken. Ego-Shooter sind ausgeklügelte „2D-Klick“-Spiele auf äußerst frustrierenden Knöpfen – oft mit einer ausgeklügelten Geschichte, um zu erklären, warum es nicht in Ordnung ist, dass diese verdammten Knöpfe Sie zurück „klicken“.
Es gibt so viele Waffen in VR, weil Waffen als genaue und zuverlässige 3D-Mäuse perfektioniert wurden – und Klicken ist das, was Verbraucher tun können, ohne es zu lernen.
Projektion bietet auch Distanzsicherheit im Verhältnis zur Szene. Denken Sie daran, dass die Annäherung an etwas in VR natürlich alle anderen Dinge ausschließt, deren Bedeutung möglicherweise noch nicht offenbart wurde.
Controllerlose Projektion mit dem „Blick“
Um dieses Interaktionselement in WebVR ohne Controller zu erstellen, können wir den „Blick“ des Betrachters als Sichtlinien-„Cursor“ projizieren. Dieser Cursor kann programmgesteuert verwendet werden, um mit Objekten mit einer „Sicherung“ zu interagieren. Dies wird dem Betrachter als kleiner blauer Kreis mitgeteilt. Jetzt klicken wir!
Wenn Sie sich an Lagerfeuergeschichten erinnern, je größer die Lüge, desto weniger Details sind erforderlich, um sie zu verkaufen. Eine offensichtliche und absurde „Blick“-Interaktion besteht darin, in die Sonne zu starren. Wir verwenden dieses „Anstarren“, um das Hinzufügen neuer „Schutt“-Planeten zu unserer Simulation auszulösen. Kein Zuschauer hat diese Wahl jemals in Frage gestellt – VR ist ziemlich charmant, wenn es absurd ist.
In A-Frame drücken wir die Kamera (die unsichtbare Spielfigur der Spieler) und diesen Sichtlinien-„Cursor“ als unser Kamera-Rigging aus. Wenn Sie den <a-cursor>
innerhalb der <a-camera>
platzieren, werden die Transformationen der Kamera auch auf den Cursor angewendet. Wenn der Spieler seine Spielfigur bewegt/dreht ( a-camera
), bewegt/dreht er auch seinen Blick ( a-cursor
).
// src/index.html <a-entity position="0 -12 .7" rotation="55 0 0"> <a-camera> <a-cursor color="#4CC3D9" fuse="true" timeout="1"></a-cursor> </a-camera> </a-entity>
Die „Sicherung“ des Cursors wartet, bis eine volle Sekunde des „Anstarrens“ vergangen ist, bevor sie ein Ereignis ausgibt.
Ich habe die Standardbeleuchtung verwendet, damit Sie vielleicht bemerken, dass es einen unbeleuchteten „Rücken“ der Sonne gibt. Ich war zwar nicht außerhalb der Orbitalebene, aber ich glaube nicht, dass die Sonne so funktioniert. Es funktioniert jedoch für unser Tech-Demo-Poster der Realität.
Eine alternative Möglichkeit wäre, die Beleuchtung innerhalb des Kameraelements zu platzieren, sodass sie sich mit dem Benutzer bewegt. Dies würde ein intimeres - und möglicherweise gruseliges - Asteroiden-Minenerlebnis schaffen. Dies sind lustige Designentscheidungen.
Wir haben einen Integrationsplan
Damit haben wir jetzt unsere Integrationspunkte zwischen dem A-Frame <a-scene>
und unserer JavaScript-Simulation:
A-Frame <a-scene>
:
Eine benannte Sammlung für die Körper:
<a-entity></a-entity>
Ein Cursor, der Projektionsereignisse ausgibt:
<a-cursor color="#4CC3D9" fuse="true" timeout="1"></a-cursor>
Unsere JavaScript-Simulation:
nBodyVisWebVR.paint(bodies)
- Hinzufügen/Entfernen/Neupositionieren der VR-Einheiten von den SimulationskörpernaddBodyArgs(name, color, x, y, z, mass, vX, vY, vZ)
, um der Simulation neue Trümmerkörper hinzuzufügen
index.html
lädt main.js
, was unsere Simulation ähnlich wie die Canvas-Version initialisiert:
// src/main.js import { nBodyVisualizer, nBodyVisWebVR } from ."/nBodyVisualizer" import { Body, nBodySimulator } from ."/nBodySimulator" window.onload = function() { // Create a Simulation const sim = new nBodySimulator() // this Visualizer manages the UI sim.addVisualization(new nBodyVisWebVR(document.getElementById("a-bodies"), sim)) // making up stable universes is hard // name color xyzm vz vy vz sim.addBody(new Body("star", "yellow", 0, 0, 1, 1e9)) sim.addBody(new Body("hot-jupiter", "red", -1, -1, 1, 1e4, .24, -0.05, 0)) sim.addBody(new Body("cold-jupiter", "purple", 4, 4, .5, 1e4, -.07, 0.04, 0)) // Start simulation sim.start() // Add another sim.addBody(new Body("saturn", "blue", -8, -8, .1, 1e3, .07, -.035, 0)) }
Sie werden feststellen, dass wir hier das htmlElement
des Visualizers auf die Sammlung a-bodies
gesetzt haben, um die Körper aufzunehmen.
Programmatisches Verwalten von A-Frame-Objekten aus JavaScript
Nachdem wir unsere Szene in index.html
deklariert haben, können wir nun den Visualizer codieren.
Zuerst richten wir nBodyVisualizer
nBodySimulation
und A-Frame-Objekte in der Sammlung <a-entity></a-entity>
erstellt/aktualisiert/löscht.
// src/nBodyVisualizer.js /** * This is the WebVR visualizer. * It's responsible for painting and setting up the entire scene. */ export class nBodyVisWebVR extends nBodyVisualizer { constructor(htmlElement, sim) { // HTML Element is a-collection#a-bodies. super(htmlElement) // We add these to the global namespace because // this isn't the core problem we are trying to solve. window.sim = sim this.nextId = 0 } resize() {}
Im Konstruktor speichern wir unsere A-Frame-Sammlung, legen eine globale Variable für unser Blickereignis fest, um die Simulation zu finden, und initialisieren einen ID-Zähler, den wir verwenden, um Körper zwischen unserer Simulation und der Szene von A-Frame abzugleichen.
paint(bodies) { let i // Create lookup table: lookup[body.aframeId] = body const lookup = bodies.reduce( (total, body) => { // If new body, give it an aframeId if (!body.aframeId) body.aframeId = `a-sim-body-${body.name}-${this.nextId++}` total[body.aframeId] = body return total }, {}) // Loop through existing a-sim-bodies and remove any that are not in // the lookup - this is our dropped debris const aSimBodies = document.querySelectorAll(."a-sim-body") for (i = 0; i < aSimBodies.length; i++) { if (!lookup[aSimBodies[i].id]) { // if we don't find the scene's a-body in the lookup table of Body()s, // remove the a-body from the scene aSimBodies[i].parentNode.removeChild(aSimBodies[i]); } } // loop through sim bodies and upsert let aBody bodies.forEach( body => { // Find the html element for this aframeId aBody = document.getElementById(body.aframeId) // If html element not found, make one. if (!aBody) { this.htmlElement.innerHTML += ` <a-sphere class="a-sim-body" dynamic-body ${ (body.name === "star") ? "debris-listener event-set__enter='_event: mouseenter; color: green' event-set__leave='_event: mouseleave; color: yellow'" : ""} position="0 0 0" radius="${body.drawSize/this.scaleSize}" color="${body.color}"> </a-sphere>` aBody = document.getElementById(body.aframeId) } // reposition aBody.object3D.position.set(body.x, body.y, body.z) }) }
Zuerst durchlaufen wir die Simulationskörper, um eine Nachschlagetabelle zu beschriften und/oder zu erstellen, um A-Frame-Entitäten mit Simulationskörpern abzugleichen.
Als nächstes durchlaufen wir die vorhandenen A-Frame-Körper und entfernen alle, die von der Simulation für das Fahren außerhalb der Grenzen getrimmt wurden. Dies erhöht die wahrgenommene Leistung des Erlebnisses.
Schließlich durchlaufen wir die simulierten Körper, um eine neue <a-sphere>
für fehlende Körper zu erstellen und die anderen mit aBody.object3D.position.set(body.x, body.y, body.z)
neu zu positionieren.
Wir können Elemente in der A-Frame-Szene mit Standard-DOM-Funktionen programmgesteuert ändern. Um der Szene ein Element hinzuzufügen, hängen wir einen String an das innerHTML des Containers an. Dieser Code schmeckt mir komisch, aber er funktioniert, und ich habe nichts Besseres gefunden.
Sie werden feststellen, dass wir beim Erstellen der anzuhängenden Zeichenfolge einen ternären Operator in der Nähe von „Stern“ haben, um ein Attribut festzulegen.
<a-sphere class="a-sim-body" dynamic-body ${ (body.name === "star") ? "debris-listener event-set__enter='_event: mouseenter; color: green' event-set__leave='_event: mouseleave; color: yellow'" : ""} position="0 0 0" radius="${body.drawSize/this.scaleSize}" color="${body.color}"> </a-sphere>`
Wenn der Körper ein „Stern“ ist, fügen wir einige zusätzliche Attribute hinzu, die seine Ereignisse beschreiben. So sieht unser Stern aus, wenn er im DOM montiert ist:
<a-sphere class="a-sim-body" dynamic-body="" debris-listener="" event-set__enter="_event: mouseenter; color: green" event-set__leave="_event: mouseleave; color: yellow" position="0 0 0" radius="0.36" color="yellow" material="" geometry=""></a-sphere>
Drei Attribute, „detrument debris-listener
“, event-set__enter
und „ event-set__leave
, richten unsere Interaktionen ein und sind die letzte Runde unserer Integration.
Definieren von A-Frame-Ereignissen und -Interaktionen
Wir verwenden das NPM-Paket „aframe-event-set-component“ in den Attributen der Entity, um die Farbe der Sonne zu ändern, wenn der Betrachter darauf „schaut“.
Dieser „Blick“ ist eine Projektion der Position und Drehung des Betrachters, und die Interaktion liefert das notwendige Feedback, dass sein Blick etwas tut.
Unsere Sternenkugel hat jetzt zwei vom Plugin aktivierte Kurzschreibereignisse, event-set__enter
und event-set__leave
:
<a-sphere ... event-set__enter="_event: mouseenter; color: green" event-set__leave="_event: mouseleave; color: yellow" … ></a-sphere>
Als nächstes schmücken wir unsere Sternkugel mit einem debris-listener
, den wir als benutzerdefinierte A-Frame-Komponente implementieren werden.
<a-sphere ... debris-listener="" … ></a-sphere>
A-Frame-Komponenten werden auf globaler Ebene definiert:
// src/nBodyVisualizer.js // Component to add new bodies when the user stares at the sun. See HTML AFRAME.registerComponent('debris-listener', { init: function () { // Helper function function rando(scale) { return (Math.random()-.5) * scale } // Add 10 new bodies this.el.addEventListener('click', function (evt) { for (let x=0; x<10; x++) { // name, color, x, y, z, mass, vx, vy, vz window.sim.addBodyArgs("debris", "white", rando(10), rando(10), rando(10), 1, rando(.1), rando(.1), rando(.1)) } }) } })
Diese A-Frame-Komponente verhält sich wie ein „Klick“-Listener, der durch den Blickcursor ausgelöst werden kann, um unserer Szene 10 neue zufällige Körper hinzuzufügen.
Zusammenfassen:
- Wir deklarieren die WebVR-Szene mit A-Frame in Standard-HTML.
- Wir können A-Frame-Entitäten in der Szene programmgesteuert aus JavaScript hinzufügen/entfernen/aktualisieren.
- Wir können Interaktionen in JavaScript mit Event-Handlern über A-Frame-Plugins und -Komponenten erstellen.
WebVR: Veni, Vidi, Vici
Ich hoffe, Sie haben genauso viel aus dieser Tech-Demo herausgeholt wie ich. Wo wir diese Funktionen (Webworker und WebAssembly) auf WebVR angewendet haben, können sie auch auf Browser-Edge-Computing angewendet werden.
Eine riesige Technologiewelle ist angekommen - Virtual Reality (VR). Was auch immer Sie gefühlt haben, als Sie zum ersten Mal ein Smartphone in der Hand hielten, VR zum ersten Mal zu erleben, bietet ein 10-mal emotionaleres Erlebnis in jedem Aspekt des Computers. Seit dem ersten iPhone sind nur 12 Jahre vergangen.
VR gibt es schon viel länger, aber die Technologie, die erforderlich ist, um VR für durchschnittliche Benutzer bereitzustellen, ist über die mobile Revolution und Facebooks Oculus Quest angekommen – nicht über die PC-Revolution.
Das Internet und Open Source gehören zu den größten Weltwundern der Menschheit. An alle Menschen, die das flache Internet geschaffen haben – ich stoße auf Ihren Mut und Ihre Abenteuerlust an.
Manifest! Wir werden Welten bauen, denn wir haben die Macht zu erschaffen.