WebVR 파트 5: 설계 및 구현

게시 됨: 2022-03-11

나는 프로젝트를 "완료"하는 것을 좋아합니다. 우리는 여정의 끝에 도달했으며 WebVR에서 천체 중력 시뮬레이션이 탄생했습니다.

이 마지막 게시물에서는 고성능 시뮬레이션 코드(1,2,3항)를 캔버스 시각화 장치(4항)를 기반으로 하는 WebVR 시각화 장치에 연결합니다.

  1. "n-body problem" 소개 및 아키텍처
  2. 웹 작업자는 추가 브라우저 스레드를 얻습니다.
  3. O(n²) 성능 병목 코드용 WebAssembly 및 AssemblyScript
  4. 캔버스 데이터 시각화
  5. WebVR 데이터 시각화

이것은 더 긴 기사이므로 이전에 다룬 몇 가지 기술적인 세부사항은 건너뛰겠습니다. 오리엔테이션을 원하는 경우 이전 게시물을 확인하거나 위험하게 읽으십시오.

우리는 단일 스레드 JavaScript 런타임에서 다중 스레드(웹 작업자) 고성능 런타임(WebAssembly)으로 브라우저의 패러다임 전환을 탐구해 왔습니다. 이러한 고성능 데스크탑 컴퓨팅 기능은 Progressive Web Apps 및 SaaS 배포 모델에서 사용할 수 있습니다.

WebVR 데모
WebVR 데모, 예제 코드

VR은 의사 소통, 설득 및 참여 측정(시선 추적 및 상호 작용)을 위해 주의가 산만하지 않은 매력적인 판매 및 마케팅 환경을 만듭니다. 데이터는 여전히 0과 1이지만 예상되는 요약 및 소비자 경험은 WebVR이 될 것입니다. 마치 오늘날 플랫 웹을 위한 모바일 대시보드 경험을 구축하는 것과 같습니다.

이러한 기술은 또한 분산 브라우저 에지 컴퓨팅을 가능하게 합니다. 예를 들어 시뮬레이션에서 수백만 개의 별에 대한 WebAssembly 계산을 실행하는 웹 기반 응용 프로그램을 만들 수 있습니다. 또 다른 예는 다른 사용자의 창작물을 편집하는 동안 다른 사용자의 창작물을 렌더링하는 애니메이션 응용 프로그램입니다.

엔터테인먼트 콘텐츠는 모바일에서 주도하는 엔터테인먼트와 마찬가지로 가상 현실의 도입을 주도하고 있습니다. 그러나 VR이 정상화되면(오늘날 모바일 퍼스트 디자인과 같이) 예상되는 경험이 될 것입니다(VR 퍼스트 디자인). 지금은 디자이너와 개발자에게 매우 흥미로운 시기이며 VR은 완전히 다른 디자인 패러다임입니다.

잡을 수 없다면 VR 디자이너가 아닙니다. 그것은 대담한 진술이며 오늘은 VR 디자인에 대한 심층 분석입니다. 이 분야는 당신이 이것을 읽는 동안 발명되고 있습니다. 제 목적은 소프트웨어와 영화에 대한 제 경험을 공유하여 "VR 우선 디자인" 대화를 시작하는 것입니다. 우리는 모두 서로에게서 배운다.

이러한 장대한 예측을 염두에 두고 이 프로젝트를 전문 기술 데모로 완료하고 싶었습니다. WebVR은 이를 위한 탁월한 선택입니다!

WebVR 및 Google A-Frame

WebVR git repo는 몇 가지 이유로 캔버스 버전의 포크입니다. 이를 통해 Github 페이지에서 프로젝트를 더 쉽게 호스팅할 수 있으며 WebVR에는 캔버스 버전과 이러한 기사를 어지럽힐 수 있는 몇 가지 변경 사항이 필요했습니다.

아키텍처에 대한 첫 번째 게시물을 기억한다면 전체 시뮬레이션을 nBodySimulator 에 위임했습니다.

`nBodySimulator`

웹 작업자 게시물은 nBodySimulator 에 시뮬레이션의 33ms마다 호출되는 step() 함수가 있음을 보여주었습니다. step() 은 O(n²) WebAssembly 시뮬레이션 코드(3조 calculateForces() 를 실행하기 위해 computeForces()를 호출한 다음 위치를 업데이트하고 다시 그립니다. 캔버스 시각화를 만드는 이전 게시물에서 이 기본 클래스에서 시작하여 캔버스 요소로 이것을 구현했습니다.

 /** * 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)) } }

통합 과제 정의

시뮬레이션이 있습니다. 이제 우리는 프로젝트를 재설계하지 않고 WebVR과 통합하고자 합니다. 우리가 시뮬레이션에 적용하는 모든 조정은 paint(bodies) 함수의 기본 UI 스레드에서 33ms마다 발생합니다.

이것이 우리가 "완료"를 측정하는 방법입니다. 나는 흥분된다 - 일하러 가자!

가상 현실을 만드는 방법

먼저 디자인이 필요합니다.

  • VR은 무엇으로 만들어 졌나요?
  • WebVR 디자인은 어떻게 표현 되나요?
  • 어떻게 상호 작용할 수 있습니까?

가상 현실은 시간의 새벽으로 거슬러 올라갑니다. 모든 모닥불 이야기는 사소한 세부 사항으로 덮인 이상한 과장의 작은 가상 세계입니다.

3D 입체 영상과 오디오를 추가하여 캠프파이어 스토리를 10배 늘릴 수 있습니다. 내 영화 제작 예산 강사 는 "우리는 포스터 비용만 지불합니다. 우리는 현실을 구축하고 있지 않습니다.”

브라우저 DOM에 익숙하다면 이것이 트리와 같은 계층 구조를 생성한다는 것을 알게 될 것입니다.

평면 웹 장면 그래프
평면 웹 "장면 그래프."

웹 디자인에 내포된 것은 "정면"에서 보는 뷰어입니다. 측면에서 보면 DOM 요소가 선으로 표시되고 후면에서 보면 자식을 가리기 때문에 <body> 태그만 보입니다.

VR의 몰입형 경험 중 일부는 사용자가 자신의 관점, 스타일, 속도 및 상호 작용 순서를 제어할 수 있도록 하는 것입니다. 그들은 특별히 어떤 것에 주의를 기울일 필요가 없습니다. 프로그래밍 방식으로 카메라를 이동하거나 회전하면 말 그대로 VR 멀미로 토할 것입니다.

VR 멀미가 장난이 아닙니다. 우리의 눈과 내이는 모두 움직임을 감지합니다. 똑바로 걷는 동물에게는 매우 중요합니다. 이러한 움직임 센서가 동의하지 않을 때, 우리의 뇌는 자연스럽게 우리의 입이 다시 말도 안되는 음식을 먹고 있다고 가정하고 토합니다. 우리는 모두 한때 어린이였습니다. VR에서 이러한 생존 본능에 대해 이미 많은 글이 작성되었습니다. "Epic Fun" 타이틀은 Steam에서 무료이며 롤러코스터는 내가 찾은 최고의 VR 멀미 데모입니다.

가상 현실은 "장면 그래프"로 표현됩니다. 장면 그래프는 DOM과 동일한 나무 모양의 패턴을 사용하여 설득력 있는 3D 환경의 세부 사항과 복잡성을 숨깁니다. 그러나 스크롤 및 라우팅 대신 시청자가 경험을 원하는 위치에 배치합니다.

다음은 Google A-Frame WebVR 프레임워크의 Hello World 장면 그래프입니다.

 <!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>

이 HTML 문서는 브라우저에서 DOM을 생성합니다. <a-*> 태그는 A-Frame 프레임워크의 일부이고 <a-scene> 은 장면 그래프의 루트입니다. 여기에서 장면에 4개의 3D 프리미티브가 표시됩니다.

플랫 웹 브라우저의 A-Frame 장면
플랫 웹 브라우저의 A-Frame 장면.

먼저 플랫 웹 브라우저에서 장면을 보고 있음을 확인하십시오. 오른쪽 아래에 있는 작은 마스크는 3D 입체 모드로 전환하도록 사용자를 초대합니다.

가상 현실의 A-Frame 장면
가상 현실의 A-프레임 장면 - 각 눈에 대해 하나의 이미지.

이론적으로 다음을 수행할 수 있어야 합니다.

  1. 휴대전화에서 이 항목을 엽니다.
  2. 휴대전화를 얼굴에 대세요.
  3. 새로운 현실의 화려함을 즐기십시오!

VR 헤드셋의 멋진 렌즈 없이는 작동하지 않습니다. 안드로이드 폰용 VR 헤드셋은 저렴한 가격(구글 카드보드 기반의 기본 기기)으로 구할 수 있지만 콘텐츠 개발을 위해서는 오큘러스 퀘스트와 같은 독립형 HMD(Head Mounted Display)를 추천한다.

스쿠버 다이빙이나 스카이다이빙과 마찬가지로 가상 현실은 기어 스포츠입니다.

VR 디자이너의 배움 '절벽'

중력과 빛이 있는 현실
중력과 빛이 있는 이 편안한 현실에 오신 것을 환영합니다.

A-Frame Hello World 장면에는 기본 조명과 카메라가 있습니다.

  • 정육면체의 면은 서로 다른 색상입니다. 정육면체는 자체 음영 처리됩니다.
  • 큐브가 평면에 그림자를 드리우고 있습니다. 방향 조명이 있습니다.
  • 큐브와 평면 사이에는 간격이 없습니다. 이것은 중력이 있는 세계입니다.

이것은 시청자에게 "진정하세요. 얼굴에 묻은 것은 완전히 정상입니다." 라고 말하는 중요한 단서입니다.

또한 이 기본 설정은 위의 Hello World 장면의 코드에 암시되어 있습니다. A-Frame은 현명하게 합리적인 기본값을 제공하지만 주의하십시오. 카메라와 조명은 플랫 웹 디자이너가 VR을 만들기 위해 건너야 하는 틈입니다.

우리는 기본 조명 설정을 당연하게 여깁니다. 예를 들어 버튼은 다음과 같습니다.

버튼

이 암시적 조명이 디자인과 사진에 얼마나 널리 퍼져 있는지 주목하십시오. "평면 디자인" 버튼도 웹의 기본 조명을 벗어날 수 없습니다. 오른쪽 아래로 그림자가 드리워집니다.

조명 및 카메라 설정을 설계, 커뮤니케이션 및 구현하는 것은 WebVR 디자이너의 학습 절벽입니다. "Language of Film" 은 다양한 카메라와 조명 설정으로 표현되는 문화적 규범의 모음으로 관객에게 이야기를 감정적으로 전달합니다. 장면에서 조명과 카메라를 디자인/움직이는 영화 전문가는 그립 부서입니다.

가상 현실로 돌아가기

자, 이제 다시 작업으로 돌아가 보겠습니다. 우리의 천상의 WebVR 장면은 비슷한 패턴을 가지고 있습니다.

 <!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>

이 HTML 문서는 A-Frame 프레임워크와 상호작용 플러그인을 로드합니다. 우리의 장면은 <a-scene> 에서 시작됩니다.

내부에서 <a-sky color="#222"></a-sky> 요소로 시작하여 장면에서 정의하지 않은 모든 것을 배경색으로 지정합니다.

다음으로 우리는 시청자가 우리의 이상하고 미지의 세계를 날아갈 때 "붙잡을" 수 있도록 "궤도 평면"을 만듭니다. 이것을 디스크와 (0,0,0)에서 작은 검은색 구로 만듭니다. 이것이 없다면 터닝은 나에게 "근거 없는" 느낌이 들었다.

 <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-Frame 엔터티를 추가/제거/재배치할 수 있는 컬렉션을 정의합니다.

 <a-entity></a-entity>

이것은 nBodyVisualizerpaint(bodies) 가 작업을 수행하기 위한 지우기입니다.

그런 다음 보는 사람과 이 세계의 관계를 만듭니다. 기술 데모로서 이 세상의 목적은 시청자가 WebVR과 이를 가능하게 하는 브라우저 기술을 탐색할 수 있도록 하는 것입니다. 단순한 "우주비행사" 내러티브는 놀이감을 느끼게 하며, 이 별표 표지판은 항해를 위한 또 다른 기준점이 됩니다.

 <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>

이로써 장면 그래프가 완성되었습니다. 마지막으로, 전화 데모에서 사용자와 이 꼬불꼬불한 세상 사이의 일종의 상호 작용을 원했습니다. VR에서 "쓰레기 던지기" 버튼을 어떻게 다시 만들 수 있습니까?

버튼은 모든 현대적인 디자인의 기본 요소입니다. VR 버튼은 어디에 있습니까?

WebVR의 상호 작용

가상 현실에는 고유한 "위"와 "폴드 아래"가 있습니다. 시청자의 첫 번째 상호 작용은 아바타 또는 카메라를 통해 이루어집니다. 이것은 확대/축소하는 모든 컨트롤입니다.

데스크탑에서 이 글을 읽고 있다면 WASD로 이동하고 마우스로 카메라를 회전할 수 있습니다. 이 탐색은 정보를 드러내지만 당신의 의지를 표현하지는 않습니다.

Real Reality에는 웹에서 자주 볼 수 없는 몇 가지 매우 중요한 기능이 있습니다.

  • 원근법 - 물체가 우리에게서 멀어질수록 눈에 띄게 작아집니다.
  • 오클루전 - 위치에 따라 개체를 숨기고 표시합니다.

VR은 이러한 기능을 시뮬레이션하여 3D 효과를 만듭니다. VR에서 정보와 인터페이스를 표시하고 상호 작용을 제공하기 전에 분위기를 설정하는 데 사용할 수도 있습니다. 나는 대부분의 사람들이 앞으로 나아가기 전에 경험을 즐기는 데 1분이 필요하다는 것을 발견했습니다.

WebVR에서 우리는 3D 공간에서 상호 작용합니다. 이를 위한 두 가지 기본 도구가 있습니다.

  • 충돌 - 두 개체가 동일한 공간을 공유할 때 발생하는 수동 3D 이벤트입니다.
  • 투영 - 선을 교차하는 모든 객체를 나열하는 활성 2D 함수 호출입니다.

충돌은 가장 "VR과 유사한" 상호 작용입니다.

VR에서 "충돌"은 정확히 같은 소리입니다. 두 개체가 같은 공간을 공유할 때 A-Frame은 이벤트를 생성합니다.

사용자가 버튼을 "누르려면" 폰과 버튼을 누를 무언가를 제공해야 합니다.

불행히도 WebVR은 아직 컨트롤러를 가정할 수 없습니다. 많은 사람들이 데스크톱이나 휴대전화에서 플랫 웹 버전을 보고 Google Cardboard 또는 삼성의 Gear VR과 같은 헤드셋을 사용하여 입체 버전을 표시할 것입니다.

사용자에게 컨트롤러가 없으면 손을 뻗어 물건을 "만질" 수 없으므로 모든 충돌은 "개인 공간"에서 발생해야 합니다.

우리는 플레이어에게 우주 비행사 모양의 폰을 주어 이리저리 움직이게 할 수 있지만 사용자를 행성의 소용돌이 치는 독기로 강제하는 것은 다소 불쾌하고 우리 디자인의 넓음에 반대되는 것처럼 보입니다.

투영은 3D 공간에서 2D "웹과 같은" 클릭입니다.

"충돌" 외에 "투영"도 사용할 수 있습니다. 우리는 장면을 통해 선을 투영하고 그것이 무엇에 닿는지 볼 수 있습니다. 가장 일반적인 예는 "텔레포트 레이"입니다.

순간이동 광선은 플레이어가 이동할 수 있는 위치를 표시하기 위해 세계의 선을 추적합니다. 이 "투영"은 착륙할 장소를 찾습니다. 투영 경로에 있는 하나 이상의 개체를 반환합니다. 다음은 텔레포트 광선의 예입니다.

언리얼 엔진의 기본 콘텐츠에 있는 텔레포트 광선
언리얼 엔진의 기본 콘텐츠에 있는 텔레포트 광선입니다.

광선은 실제로 아래를 가리키는 포물선으로 구현됩니다. 이것은 던져진 물건처럼 자연스럽게 "지면"과 교차한다는 것을 의미합니다. 이것은 또한 자연스럽게 최대 순간 이동 거리를 설정합니다. 한계는 VR에서 가장 중요한 디자인 선택입니다. 다행히 현실에는 많은 자연적 한계가 있습니다.

투영은 3D 세계를 2D로 "평평하게"하므로 마우스처럼 클릭하기 위해 물건을 가리킬 수 있습니다. 1인칭 슈팅 게임은 매우 실망스러운 버튼을 "2D 클릭"하는 정교한 게임입니다. 종종 그 빌어먹을 버튼이 다시 "클릭"하는 이유를 설명하는 정교한 스토리가 있습니다.

총이 정확하고 신뢰할 수 있는 3D 마우스로 완성되었기 때문에 VR에는 총이 너무 많습니다. 소비자는 배우지 않고도 할 수 있는 방법을 알고 있습니다.

투영은 또한 장면과의 관계에서 거리의 안전성을 제공합니다. VR에서 무언가에 더 가까이 가면 중요성이 아직 밝혀지지 않았을 수 있는 다른 모든 것이 자연스럽게 가려진다는 것을 기억하십시오.

"시선"을 사용하여 컨트롤러 없이 프로젝션

컨트롤러 없이 WebVR에서 이 상호작용 프리미티브를 생성하기 위해 시청자의 "시선"을 가시선 "커서"로 투영할 수 있습니다. 이 커서는 프로그래밍 방식으로 "퓨즈"가 있는 개체와 상호 작용하는 데 사용할 수 있습니다. 이것은 시청자에게 작은 파란색 원으로 전달됩니다. 이제 클릭합니다!

모닥불 이야기를 기억한다면 거짓말이 클수록 거짓말을 파는 데 필요한 세부 정보가 줄어 듭니다. 명백하고 터무니없는 "시선" 상호작용은 태양을 응시하는 것입니다. 우리는 이 "시선"을 사용하여 시뮬레이션에 새로운 "잔해" 행성을 추가하도록 합니다. 어떤 시청자도 이 선택에 의문을 제기한 적이 없습니다. VR은 부조리할 때 매우 매력적입니다.

A-Frame에서 카메라(플레이어의 보이지 않는 폰)와 이 시선 "커서"를 카메라 리깅으로 표현합니다. <a-camera> <a-cursor> 를 배치하면 카메라의 변형이 커서에도 적용됩니다. 플레이어가 폰을 이동/회전할 때( a-camera ), 시선도 이동/회전합니다( 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>

커서의 "퓨즈"는 이벤트를 발생시키기 전에 "시선"의 1초가 지나갈 때까지 기다립니다.

기본 조명을 사용하여 태양의 "뒷면"이 꺼져 있음을 알 수 있습니다. 궤도면 밖에 나가본 적은 없지만 태양이 작동하는 방식은 그렇지 않다고 생각합니다. 그러나 현실의 기술 데모 포스터에서는 작동합니다.

다른 옵션은 카메라 요소 내부에 조명을 넣어 사용자와 함께 이동하는 것입니다. 이것은 더 친밀하고 아마도 으스스한 소행성 광부 경험을 만들 것입니다. 재미있는 디자인 선택입니다.

통합 계획이 있습니다.

이를 통해 이제 A-Frame <a-scene> 과 JavaScript 시뮬레이션 간의 통합 지점이 생겼습니다.

A-Frame <a-scene> :

  • 시체에 대한 명명된 컬렉션: <a-entity></a-entity>

  • 투영 이벤트를 발생시키는 커서: <a-cursor color="#4CC3D9" fuse="true" timeout="1"></a-cursor>

우리의 JavaScript 시뮬레이션:

  • nBodyVisWebVR.paint(bodies) - 시뮬레이션 바디에서 VR 엔터티 추가/제거/재배치

  • addBodyArgs(name, color, x, y, z, mass, vX, vY, vZ) 를 사용하여 시뮬레이션에 새 파편 본체를 추가합니다.

index.html 은 캔버스 버전과 매우 유사한 시뮬레이션을 초기화하는 main.js 를 로드합니다.

 // 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)) }

여기에서 시각화 도우미의 htmlElement 를 바디를 보유하기 위해 a-bodies 컬렉션으로 설정한 것을 알 수 있습니다.

JavaScript에서 프로그래밍 방식으로 A-Frame 개체 관리

index.html 에서 장면을 선언했으므로 이제 시각화 도우미를 코딩할 준비가 되었습니다.

먼저 nBodyVisualizer 바디 목록에서 읽고 <a-entity></a-entity> 컬렉션에서 A-Frame 개체를 생성/업데이트/삭제하도록 nBodySimulation 를 설정합니다.

 // 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() {}

생성자에서 A-Frame 컬렉션을 저장하고, 시선 이벤트에 대한 전역 변수를 설정하여 시뮬레이션을 찾고, 시뮬레이션과 A-Frame 장면 사이의 본체를 일치시키는 데 사용할 id 카운터를 초기화합니다.

 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) }) }

먼저 시뮬레이션 본체를 반복하여 레이블을 지정하거나 A-Frame 개체를 시뮬레이션 본체와 일치시키기 위한 조회 테이블을 만듭니다.

다음으로, 우리는 기존 A-Frame 바디를 반복하고 경계를 벗어나 여행하기 위해 시뮬레이션에 의해 트리밍된 바디를 제거합니다. 이것은 경험의 인지된 성능을 증가시킵니다.

마지막으로 sim 바디를 반복하여 누락된 바디에 대한 새로운 <a-sphere> 를 만들고 다른 바디를 aBody.object3D.position.set(body.x, body.y, body.z) 로 재배치합니다.

표준 DOM 기능을 사용하여 A-Frame 장면의 요소를 프로그래밍 방식으로 변경할 수 있습니다. 장면에 요소를 추가하기 위해 컨테이너의 innerHTML에 문자열을 추가합니다. 이 코드는 맛이 이상하지만 작동하며 더 나은 것을 찾지 못했습니다.

추가할 문자열을 생성할 때 속성을 설정하기 위해 "star" 근처에 삼항 연산자가 있음을 알 수 있습니다.

 <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>`

본문이 "별"인 경우 이벤트를 설명하는 몇 가지 추가 속성을 추가합니다. DOM에 마운트되었을 때 별 모양은 다음과 같습니다.

 <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>

세 가지 속성, destroyer debris-listener , event-set__enterevent-set__leave 는 상호 작용을 설정하고 통합의 마지막 랩입니다.

A-Frame 이벤트 및 상호 작용 정의

우리는 엔터티 속성에서 NPM 패키지 "aframe-event-set-component"를 사용하여 뷰어가 태양을 "볼" 때 태양의 색상을 변경합니다.

이 "시선"은 시청자의 위치와 회전에 대한 투영이며 상호 작용은 시선이 뭔가를 하고 있다는 필요한 피드백을 제공합니다.

이제 우리의 별 구체에는 플러그인에서 활성화된 두 가지 약식 이벤트인 event-set__enterevent-set__leave .

 <a-sphere ... event-set__enter="_event: mouseenter; color: green" event-set__leave="_event: mouseleave; color: yellow" … ></a-sphere>

다음으로, 맞춤형 A-Frame 구성 요소로 구현할 debris-listener 로 별 구를 장식합니다.

 <a-sphere ... debris-listener="" … ></a-sphere>

A-Frame 구성 요소는 전역 수준에서 정의됩니다.

 // 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)) } }) } })

이 A-Frame 구성 요소는 시선 커서에 의해 트리거되어 장면에 10개의 새로운 임의 바디를 추가할 수 있는 '클릭' 리스너처럼 작동합니다.

요약:

  1. 표준 HTML에서 A-Frame으로 WebVR 장면을 선언합니다.
  2. JavaScript에서 장면의 A-Frame 엔터티를 프로그래밍 방식으로 추가/제거/업데이트할 수 있습니다.
  3. A-Frame 플러그인 및 구성 요소를 통해 이벤트 핸들러를 사용하여 JavaScript에서 상호 작용을 만들 수 있습니다.

WebVR: Veni, Vidi, Vici

이 기술 데모에서 저만큼 많은 것을 얻으셨기를 바랍니다. 이러한 기능(웹 작업자 및 WebAssembly)을 WebVR에 적용한 경우 브라우저 에지 컴퓨팅에도 적용할 수 있습니다.

가상현실(VR)이라는 거대한 기술 물결이 도래했습니다. 스마트폰을 처음 들었을 때 느꼈던 것이 무엇이든 VR을 처음 경험하면 컴퓨팅의 모든 측면에서 10배의 감정적 경험을 선사합니다. 첫 아이폰 이후 12년 만이다.

VR은 훨씬 오래되었지만 일반 사용자에게 VR을 제공하는 데 필요한 기술은 PC 혁명이 아니라 모바일 혁명과 Facebook의 Oculus Quest를 통해 도착했습니다.

인터넷과 오픈 소스는 인류의 세계에서 가장 위대한 불가사의 중 하나입니다. 플랫 인터넷을 만든 모든 사람들에게 - 당신의 용기와 모험심에 건배를 드립니다.

선언서! 우리는 창조할 힘이 있기 때문에 세계를 건설할 것입니다.

WebVR 데모
캔버스 데모, WebVR 데모, 예제 코드