Como construir um modelo de realidade virtual com uma visualização em tempo real entre dispositivos

Publicados: 2022-03-10
Resumo rápido ↬ Neste tutorial, vamos programar objetos tridimensionais e adicionar interações simples a esses objetos. Além disso, você pode aprender como construir um sistema simples de troca de mensagens entre clientes e servidores.

A realidade virtual (VR) é uma experiência baseada em um ambiente gerado por computador; vários produtos diferentes de RV fazem manchetes e suas aplicações variam muito: para as Olimpíadas de inverno, a equipe dos EUA utilizou a realidade virtual para treinamento esportivo; cirurgiões estão experimentando a realidade virtual para treinamento médico; e mais comumente, a realidade virtual está sendo aplicada aos jogos.

Vamos nos concentrar na última categoria de aplicativos e focar especificamente em jogos de aventura de apontar e clicar . Esses jogos são uma classe casual de jogos; o objetivo é apontar e clicar em objetos na cena, para terminar um quebra-cabeça. Neste tutorial, vamos construir uma versão simples de tal jogo, mas em realidade virtual. Isso serve como uma introdução à programação em três dimensões e é um guia de introdução autônomo para a implantação de um modelo de realidade virtual na web. Você estará construindo com webVR, uma estrutura que oferece uma dupla vantagem - os usuários podem jogar seu jogo em VR e os usuários sem um headset de VR ainda podem jogar seu jogo em um telefone ou desktop.

Desenvolvendo para Realidade Virtual

Qualquer desenvolvedor pode criar conteúdo para VR hoje em dia. Para entender melhor o desenvolvimento de RV, trabalhar em um projeto de demonstração pode ajudar. Leia um artigo relacionado →

Na segunda metade deste tutorial, você construirá um “espelho” para sua área de trabalho. Isso significa que todos os movimentos que o jogador fizer em um dispositivo móvel serão espelhados em uma visualização de desktop. Isso permite que você veja o que o jogador vê, permitindo que você forneça orientação, grave o jogo ou simplesmente mantenha os convidados entretidos.

Pré-requisitos

Para começar, você precisará do seguinte. Para a segunda metade deste tutorial, você precisará de um Mac OSX. Considerando que o código pode ser aplicado a qualquer plataforma, as instruções de instalação de dependência abaixo são para Mac.

  • Acesso à Internet, especificamente para glitch.com;
  • Um fone de ouvido de realidade virtual (opcional, recomendado). Eu uso o Google Cardboard, que é oferecido a US$ 15 por peça.
Mais depois do salto! Continue lendo abaixo ↓

Etapa 1: configurar um modelo de realidade virtual (VR)

Nesta etapa, vamos configurar um site com uma única página HTML estática. Isso nos permite codificar a partir de sua área de trabalho e implantar automaticamente na web. O site implantado pode ser carregado em seu telefone celular e colocado dentro de um headset de RV. Como alternativa, o site implantado pode ser carregado por um headset VR autônomo. Comece navegando até glitch.com. Então,

  1. Clique em “Novo Projeto” no canto superior direito.
  2. Clique em “hello-express” no menu suspenso.
Comece navegando para glitch.com
(Visualização grande)

Em seguida, clique em views/index.html na barra lateral esquerda. Vamos nos referir a isso como seu “editor”.

O próximo passo seria clicar em views/index.html na barra lateral esquerda que será referido como seu “editor”.
(Visualização grande)

Para visualizar a página da web, clique em “Visualizar” no canto superior esquerdo. Vamos nos referir a isso como sua visualização . Observe que quaisquer alterações em seu editor serão refletidas automaticamente nesta visualização, exceto bugs ou navegadores não compatíveis.

Para visualizar a página da web, clique em “Visualizar” no canto superior esquerdo. Vamos nos referir a isso como sua visualização. Observe que quaisquer alterações em seu editor serão refletidas automaticamente nesta visualização, exceto bugs ou navegadores não compatíveis.
(Visualização grande)

De volta ao seu editor, substitua o HTML atual pelo padrão a seguir para um modelo de RV.

 <!DOCTYPE html> <html> <head> <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script> </head> <body> <a-scene> <!-- blue sky --> <a-sky color="#a3d0ed"></a-sky> <!-- camera with wasd and panning controls --> <a-entity camera look-controls wasd-controls position="0 0.5 2" rotation="0 0 0"></a-entity> <!-- brown ground --> <a-box shadow shadow="receive:true" color="#847452" width="10" height="0.1" depth="10"></a-box> <!-- start code here --> <!-- end code here --> </a-scene> </body> </html>

Navegue veja o seguinte.

Ao navegar de volta para sua visualização, você verá as cores do fundo azul e marrom.
(Visualização grande)

Para visualizar isso em seu headset de RV, use o URL no omnibar. Na imagem acima, o URL é https://point-and-click-vr-game.glitch.me/ . Seu ambiente de trabalho agora está configurado; sinta-se à vontade para compartilhar este URL com familiares e amigos. Na próxima etapa, você criará um modelo de realidade virtual.

Etapa 2: construir um modelo de árvore

Agora você criará uma árvore, usando primitivos de aframe.io. Esses são objetos padrão que o Aframe pré-programou para facilitar o uso. Especificamente, Aframe se refere a objetos como entidades . Existem três conceitos, relacionados a todas as entidades, para organizar nossa discussão em torno de:

  1. Geometria e materiais,
  2. Eixos de Transformação,
  3. Transformações Relativas.

Primeiro, geometria e material são dois blocos de construção de todos os objetos tridimensionais no código. A geometria define a “forma” – um cubo, uma esfera, uma pirâmide e assim por diante. O material define propriedades estáticas da forma, como cor, refletividade, rugosidade.

Aframe simplifica este conceito para nós definindo primitivos, como <a-box> , <a-sphere> , <a-cylinder> e muitos outros para tornar a especificação de uma geometria e seu material mais simples. Comece definindo uma esfera verde. Na linha 19 do seu código, logo após <!-- start code here --> , adicione o seguinte.

 <!-- start code here --> <a-sphere color="green" radius="0.5"></a-sphere> <!-- new line --> <!-- end code here -->

Segundo, existem três eixos para transformar nosso objeto. O eixo x corre horizontalmente, onde os valores de x aumentam à medida que nos movemos para a direita. O eixo y corre verticalmente, onde os valores de y aumentam à medida que nos movemos para cima. O eixo z sai da tela, onde os valores de z aumentam à medida que nos aproximamos de você. Podemos traduzir, girar ou dimensionar entidades ao longo desses três eixos.

Por exemplo, para traduzir um objeto “certo”, aumentamos seu valor x. Para girar um objeto como um pião, giramos ao longo do eixo y. Modifique a linha 19 para mover a esfera “para cima” – isso significa que você precisa aumentar o valor de y da esfera. Observe que todas as transformações são especificadas como <x> <y> <z> , ou seja, para aumentar seu valor y, você precisa aumentar o segundo valor. Por padrão, todos os objetos estão localizados na posição 0, 0, 0. Adicione a especificação de position abaixo.

 <!-- start code here --> <a-sphere color="green" radius="0.5" position="0 1 0"></a-sphere> <!-- edited line --> <!-- end code here -->

Terceiro, todas as transformações são relativas ao seu pai. Para adicionar um tronco à sua árvore, adicione um cilindro dentro da esfera acima. Isso garante que a posição do seu tronco seja em relação à posição da esfera. Em essência, isso mantém sua árvore unida como uma unidade. Adicione a entidade <a-cylinder> entre as tags <a-sphere ...> e </a-sphere> .

 <a-sphere color="green" radius="0.5" position="0 1 0"> <a-cylinder color="#84651e" position="0 -0.9 0" radius="0.05"></a-cylinder> <!-- new line --> </a-sphere>

Para fazer este barebones sem árvores, adicione mais folhagem, na forma de mais duas esferas verdes.

 <a-sphere color="green" radius="0.5" position="0 0.75 0"> <a-cylinder color="#84651e" position="0 -0.9 0" radius="0.05"></a-cylinder> <a-sphere color="green" radius="0.35" position="0 0.5 0"></a-sphere> <!-- new line --> <a-sphere color="green" radius="0.2" position="0 0.8 0"></a-sphere> <!-- new line --> </a-sphere>

Navegue de volta para sua visualização e você verá a seguinte árvore:

Ao navegar de volta para sua visualização, agora você poderá ver uma árvore verde colocada em seu plano de fundo.
(Visualização grande)

Recarregue a visualização do site em seu headset VR e confira sua nova árvore. Na próxima seção, tornaremos essa árvore interativa.

Etapa 3: adicionar interação de clique ao modelo

Para tornar uma entidade interativa, você precisará:

  • Adicione uma animação,
  • Faça esta animação disparar ao clicar.

Como o usuário final está usando um fone de ouvido de realidade virtual, clicar é equivalente a encarar: em outras palavras, olhe para um objeto para “clicar” nele. Para efetuar essas alterações, você começará com o cursor. Redefina a câmera, substituindo a linha 13 pelo seguinte.

 <a-entity camera look-controls wasd-controls position="0 0.5 2" rotation="0 0 0"> <a-entity cursor="fuse: true; fuseTimeout: 250" position="0 0 -1" geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03" material="color: black; shader: flat" scale="0.5 0.5 0.5" raycaster="far: 20; interval: 1000; objects: .clickable"> <!-- add animation here --> </a-entity> </a-entity>

O acima adiciona um cursor que pode acionar a ação de clicar. Observe os objects: .clickable . Isso significa que todos os objetos com a classe “clicável” acionarão a animação e receberão um comando de “clique” quando apropriado. Você também adicionará uma animação ao cursor de clique, para que os usuários saibam quando o cursor aciona um clique. Aqui, o cursor encolherá lentamente ao apontar para um objeto clicável, encaixando-se após um segundo para indicar que um objeto foi clicado. Substitua o comentário <!-- add animation here --> pelo seguinte código:

 <a-animation begin="fusing" easing="ease-in" attribute="scale" fill="backwards" from="1 1 1" to="0.2 0.2 0.2" dur="250"></a-animation>

Mova a árvore para a direita em 2 unidades e adicione a classe “clicável” à árvore, modificando a linha 29 para corresponder ao seguinte.

 <a-sphere color="green" radius="0.5" position="2 0.75 0" class="clickable">

A seguir, você irá:

  • Especifique uma animação,
  • Acione a animação com um clique.

Devido à entidade de animação fácil de usar do Aframe, ambas as etapas podem ser feitas em rápida sucessão.

Adicione uma tag <a-animation> na linha 33, logo após a tag <a-cylinder> mas antes do final da </a-sphere> .

 <a-animation begin="click" attribute="position" from="2 0.75 0" to="2.2 0.75 0" fill="both" direction="alternate" repeat="1"></a-animation>

As propriedades acima especificam várias configurações para a animação. A animação:

  • É acionado pelo evento de click
  • Modifica a position da árvore
  • Começa da posição original 2 0.75 0
  • Termina em 2.2 0.75 0 (movendo 0,2 unidades para a direita)
  • Anima ao viajar de e para o destino
  • Alterna a animação entre viajar de e para o destino
  • Repete esta animação uma vez. Isso significa que o objeto é animado duas vezes no total – uma vez para o destino e outra de volta à posição original.

Por fim, navegue até sua visualização e arraste do cursor para sua árvore. Uma vez que o círculo preto repousa sobre a árvore, a árvore se moverá para a direita e para trás.

Uma vez que o círculo preto repousa sobre a árvore, a árvore se moverá para a direita e para trás.
Pré-visualização grande

Isso conclui o básico necessário para construir um jogo de aventura de apontar e clicar, em realidade virtual. Para ver e jogar uma versão mais completa deste jogo, veja a cena curta a seguir. A missão é abrir o portão e esconder a árvore atrás do portão, clicando em vários objetos da cena.

A missão é abrir o portão e esconder a árvore atrás do portão, clicando em vários objetos da cena.
(Visualização grande)

Em seguida, configuramos um servidor nodeJS simples para servir nossa demonstração estática.

Etapa 4: configurar o servidor NodeJS

Nesta etapa, configuraremos um servidor nodeJS básico e funcional que atende ao seu modelo de RV existente. Na barra lateral esquerda do seu editor, selecione package.json .

Comece excluindo as linhas 2-4.

 "//1": "describes your app and its dependencies", "//2": "https://docs.npmjs.com/files/package.json", "//3": "updating this file will download and update your packages",

Altere o nome para mirrorvr .

 { "name": "mirrorvr", // change me "version": "0.0.1", ...

Em dependencies , adicione socket.io .

 "dependencies": { "express": "^4.16.3", "socketio": "^1.0.0", },

Atualize a URL do repositório para corresponder à sua falha atual. O projeto de falha de exemplo é denominado point-and-click-vr-game . Substitua isso pelo nome do seu projeto de falha.

 "repository": { "url": "https://glitch.com/edit/#!/point-and-click-vr-game" },

Por fim, altere a tag "glitch" para "vr" .

 "keywords": [ "node", "vr", // change me "express" ]

Verifique novamente se seu package.json agora corresponde ao seguinte.

 { "name": "mirrorvr", "version": "0.0.1", "description": "Mirror virtual reality models", "main": "server.js", "scripts": { "start": "node server.js" }, "dependencies": { "express": "^4.16.3", "socketio": "^1.0.0" }, "engines": { "node": "8.x" }, "repository": { "url": "https://glitch.com/edit/#!/point-and-click-vr-game" }, "license": "MIT", "keywords": [ "node", "vr", "express" ] }

Verifique se seu código das partes anteriores corresponde ao seguinte, em views/index.html .

 <!DOCTYPE html> <html> <head> <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script> </head> <body> <a-scene> <!-- blue sky --> <a-sky color="#a3d0ed"></a-sky> <!-- camera with wasd and panning controls --> <a-entity camera look-controls wasd-controls position="0 0.5 2" rotation="0 0 0"> <a-entity cursor="fuse: true; fuseTimeout: 250" position="0 0 -1" geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03" material="color: black; shader: flat" scale="0.5 0.5 0.5" raycaster="far: 20; interval: 1000; objects: .clickable"> <a-animation begin="fusing" easing="ease-in" attribute="scale" fill="backwards" from="1 1 1" to="0.2 0.2 0.2" dur="250"></a-animation> </a-entity> </a-entity> <!-- brown ground --> <a-box shadow shadow="receive:true" color="#847452" width="10" height="0.1" depth="10"></a-box> <!-- start code here --> <a-sphere color="green" radius="0.5" position="2 0.75 0" class="clickable"> <a-cylinder color="#84651e" position="0 -0.9 0" radius="0.05"></a-cylinder> <a-sphere color="green" radius="0.35" position="0 0.5 0"></a-sphere> <a-sphere color="green" radius="0.2" position="0 0.8 0"></a-sphere> <a-animation begin="click" attribute="position" from="2 0.75 0" to="2.2 0.75 0" fill="both" direction="alternate" repeat="1"></a-animation> </a-sphere> <!-- end code here --> </a-scene> </body> </html>

Modifique o server.js existente.

Comece importando vários utilitários NodeJS.

  • Expressar
    Este é o framework web que usaremos para executar o servidor.
  • http
    Isso nos permite lançar um daemon, ouvindo a atividade em várias portas.
  • socket.io
    A implementação de sockets que nos permite comunicar entre o lado do cliente e o lado do servidor quase em tempo real.

Ao importar esses utilitários, inicializamos adicionalmente o aplicativo ExpressJS. Observe que as duas primeiras linhas já estão escritas para você.

 var express = require('express'); var app = express(); /* start new code */ var http = require('http').Server(app); var io = require('socket.io')(http); /* end new code */ // we've started you off with Express,

Com os utilitários carregados, o servidor fornecido instrui o servidor a retornar index.html como a página inicial. Observe que não há código novo escrito abaixo; esta é simplesmente uma explicação do código-fonte existente.

 // https://expressjs.com/en/starter/basic-routing.html app.get('/', function(request, response) { response.sendFile(__dirname + '/views/index.html'); });

Por fim, o código-fonte existente instrui o aplicativo a vincular e escutar uma porta, que é 3000 por padrão, a menos que especificado de outra forma.

 // listen for requests :) var listener = app.listen(process.env.PORT, function() { console.log('Your app is listening on port ' + listener.address().port); });

Quando terminar de editar, o Glitch recarrega automaticamente o servidor. Clique em “Mostrar” no canto superior esquerdo para visualizar seu aplicativo.

Seu aplicativo da web agora está funcionando. Em seguida, enviaremos mensagens do cliente para o servidor.

Etapa 5: enviar informações do cliente para o servidor

Nesta etapa, usaremos o cliente para inicializar uma conexão com o servidor. O cliente informará adicionalmente ao servidor se é um telefone ou um desktop. Para começar, importe o arquivo Javascript que vai existir em breve em seu views/index.html .

Após a linha 4, inclua um novo script.

 <script src="/client.js" type="text/javascript"></script>

Na linha 14, adicione camera-listener à lista de propriedades da entidade camera.

 <a-entity camera-listener camera look-controls...> ... </a-entity>

Em seguida, navegue até public/client.js na barra lateral esquerda. Exclua todo o código Javascript neste arquivo. Em seguida, defina uma função de utilitário que verifique se o cliente é um dispositivo móvel.

 /** * Check if client is on mobile */ function mobilecheck() { var check = false; (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[aw])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); return check; };

Em seguida, definiremos uma série de mensagens iniciais para trocar com o lado do servidor. Defina um novo objeto socket.io para representar a conexão do cliente com o servidor. Depois que o soquete se conectar, registre uma mensagem no console.

 var socket = io(); socket.on('connect', function() { console.log(' * Connection established'); });

Verifique se o dispositivo é móvel e envie as informações correspondentes ao servidor, usando a função emit .

 if (mobilecheck()) { socket.emit('newHost'); } else { socket.emit('newMirror'); }

Isso conclui o envio da mensagem do cliente. Agora, altere o código do servidor para receber esta mensagem e reaja adequadamente. Abra o arquivo server.js do servidor.

Lide com novas conexões e escute imediatamente o tipo de cliente. No final do arquivo, adicione o seguinte.

 /** * Handle socket interactions */ io.on('connection', function(socket) { socket.on('newMirror', function() { console.log(" * Participant registered as 'mirror'") }); socket.on('newHost', function() { console.log(" * Participant registered as 'host'"); }); });

Novamente, visualize o aplicativo clicando em “Mostrar” no canto superior esquerdo. Carregue esse mesmo URL em seu dispositivo móvel. No seu terminal, você verá o seguinte.

 listening on *: 3000 * Participant registered as 'host' * Participant registered as 'mirror'

Esta é a primeira passagem de mensagens simples, onde nosso cliente envia informações de volta ao servidor. Saia do processo NodeJS em execução. Para a parte final desta etapa, faremos com que o cliente envie as informações da câmera de volta ao servidor. Abra public/client.js .

No final do arquivo, inclua o seguinte.

 var camera; if (mobilecheck()) { AFRAME.registerComponent('camera-listener', { tick: function () { camera = this.el.sceneEl.camera.el; var position = camera.getAttribute('position'); var rotation = camera.getAttribute('rotation'); socket.emit('onMove', { "position": position, "rotation": rotation }); } }); }

Salvar e fechar. Abra o arquivo do servidor server.js para escutar este evento onMove .

Adicione o seguinte, no bloco newHost do seu código de soquete.

 socket.on('newHost', function() { console.log(" * Participant registered as 'host'"); /* start new code */ socket.on('onMove', function(data) { console.log(data); }); /* end new code */ });

Mais uma vez, carregue a visualização em seu desktop e em seu dispositivo móvel. Assim que um cliente móvel estiver conectado, o servidor começará imediatamente a registrar a posição da câmera e as informações de rotação, enviadas do cliente para o servidor. Em seguida, você implementará o inverso, onde enviará informações do servidor de volta ao cliente.

Etapa 6: enviar informações do servidor para o cliente

Nesta etapa, você enviará as informações da câmera de um host para todos os espelhos. Abra o arquivo principal do servidor, server.js .

Altere o manipulador de eventos onMove para o seguinte:

 socket.on('onMove', function(data) { console.log(data); // delete me socket.broadcast.emit('move', data) });

O modificador de broadcast garante que o servidor envie essas informações para todos os clientes conectados ao soquete, exceto para o remetente original. Depois que essas informações são enviadas a um cliente, você precisa configurar a câmera do espelho de acordo. Abra o script do cliente, public/client.js .

Aqui, verifique se o cliente é um desktop. Em caso afirmativo, receba os dados de movimentação e registre de acordo.

 if (!mobilecheck()) { socket.on('move', function(data) { console.log(data); }); }

Carregue a visualização em seu desktop e em seu dispositivo móvel. No navegador da área de trabalho, abra o console do desenvolvedor. Em seguida, carregue o aplicativo no seu celular. Assim que o celular carregar o aplicativo, o console do desenvolvedor em sua área de trabalho deve acender com a posição e a rotação da câmera.

Abra o script do cliente mais uma vez, em public/client.js . Finalmente ajustamos a câmera do cliente dependendo das informações enviadas.

Altere o manipulador de eventos acima para o evento de move .

 socket.on('move', function(data) { /* start new code */ camera.setAttribute('rotation', data["rotation"]); camera.setAttribute('position', data["position"]); /* end new code */ });

Carregue o aplicativo na área de trabalho e no telefone. Cada movimento do seu telefone é refletido no espelho correspondente na sua área de trabalho! Isso conclui a parte espelhada do seu aplicativo. Como usuário de desktop, agora você pode visualizar o que seu usuário móvel vê. Os conceitos apresentados nesta seção serão cruciais para o desenvolvimento deste jogo, pois transformamos um jogo single-player em um multiplayer.

Conclusão

Neste tutorial, programamos objetos tridimensionais e adicionamos interações simples a esses objetos. Além disso, você construiu um sistema simples de troca de mensagens entre clientes e servidores, para efetuar uma visualização de desktop do que seus usuários móveis veem.

Esses conceitos se estendem além da webVR, pois a noção de geometria e material se estende ao SceneKit no iOS (que está relacionado ao ARKit), Three.js (o backbone do Aframe) e outras bibliotecas tridimensionais. Esses blocos de construção simples juntos nos permitem ampla flexibilidade na criação de um jogo de aventura de apontar e clicar completo. Mais importante, eles nos permitem criar qualquer jogo com uma interface baseada em cliques.

Aqui estão vários recursos e exemplos para explorar melhor:

  • MirrorVR
    Uma implementação completa da visualização ao vivo criada acima. Com apenas um único link Javascript, adicione uma visualização ao vivo de qualquer modelo de realidade virtual no celular a um desktop.
  • Pouco a pouco
    Uma galeria de desenhos infantis e o modelo de realidade virtual correspondente a cada desenho.
  • Um quadro
    Exemplos, documentação do desenvolvedor e mais recursos para desenvolvimento de realidade virtual.
  • Experiências do Google Cardboard
    Experiências para a sala de aula com ferramentas personalizadas para educadores.

Da próxima vez, construiremos um jogo completo, usando web sockets para facilitar a comunicação em tempo real entre os jogadores em um jogo de realidade virtual. Sinta-se à vontade para compartilhar seus próprios modelos nos comentários abaixo.