Help us understand the problem. What is going on with this article?

ブラウザで閲覧できるVRポートフォリオを作った

Oculus Questを購入後に色々見ていると、ブラウザでVRができるWebVRというものを知りました。しかもA-Frameというフレームワークがあり、HTMLとJavaScriptで簡単にVR空間が作れるということでしばらく遊んでみてとても楽しいことがわかりました。

丁度自分のポートフォリオをどうしようか悩んでいたときだったこともあったため、せっかくなのでVRポートフォリオを作ってみることにしました。

で、実際に出来たものが下記です。

A-FrameはWebVRに対応しているものですが、普通にブラウザで3Dの描画もできるため、せっかくなのでVRに対応していないPCやスマホでもある程度操作できるようにしてみました。

記事の最後にURLもありますので是非実際に見てみてください。

入れたもの

A-Frameには組み込むだけで簡単に色々と拡張できるコンポーネントが作られてGitHub上に公開されています。今回実際に何を入れているのかを紹介していきます。

Super Hands

wmurphyrd/aframe-super-hands-component: 👐All-in-one natural hand controller, pointer, and gaze interaction library for A-Frame

Oculus Questのコントローラではグリップボタンという握りしめるような操作のボタンがあり、普通に手で物を持つようにVR空間のオブジェクトを持ち上げたり動かしたりすることが出来ます。それを簡単に実現してくれるためのA-Frame用コンポーネントです。

上記のようにオブジェクトを掴むだけであれば下記のようなちょっとしたHTMLだけで実現できます。JavaScriptも不要です。

  <a-scene>
    <a-assets></a-assets>
    <a-entity>
      <a-camera></a-camera>
      <a-entity sphere-collider="objects: a-box" super-hands hand-controls="left"></a-entity>
      <a-entity sphere-collider="objects: a-box" super-hands hand-controls="right"></a-entity>
    </a-entity>
    <a-box hoverable grabbable stretchable draggable dropppable color="blue" position="0 0 -1"></a-box>
  </a-scene>

ポートフォリオにははっきり言って全く関係ないのですが、とりあえず箱を置いて操作できるようにしておきました。

物理エンジン

簡単に物理エンジンを導入できるコンポーネントもあります。

donmccurdy/aframe-physics-system: Physics system for A-Frame VR, built on CANNON.js.
wmurphyrd/aframe-physics-extras: 🔧Cannon API interface components the A-Frame Physics System

extrasの方はSuper Handsの作者の方が簡単に物理空間上でオブジェクトを操作できるようにしてくれているコンポーネントです。

これをSuper Handsと合わせて入れることで箱を投げたりすることが出来ます。(ただしこれも全然ポートフォリオ的には意味はありません。なんとなく入れているだけです)

パネル & raycaster

適当に配置している制作物毎のパネルです。

これ自体はa-planeやa-imageを適当に組み合わせて並べているだけです。ただ、一応実際にサービスのURLにアクセスできるようにしてあります。VRでない場合はクリックでアクセスできますし、VRの場合はraycasterというレーザーポインターのようなものでクリックできます。Super Handsは最初からクリックイベントを使ってくれるようになっているため、普通にonclickを入れておけば両方で動作します。

        <a-plane
          mylink
          onclick="location.href='https://crieit.net'"

クリックできる対象はraycaster側で設定できます。

        raycaster="showLine: true; objects: [mylink], .checkpoint, a-link"

ラジコン

スティックで操作できるラジコンも無意味に置いておきました。

これは自作で、作り方は下記で紹介しています。なんかここまでやるとゲームとか作りたくなってしまいますね。

A-FrameでVRラジコンを作る - Crieit

ちなみにポートフォリオは当然一般公開したかったため仕方なくモデルは適当に作りました。フリーの素材と比べてかなりの低クオリティで悲しいです。

墓地

閉鎖したサービスの墓地です……。

PC、スマホに対応

本当にVRだけだとOculus Questを持っている人しか体験できないため、PC、スマホでも操作できるように、とりあえず最低限ではありますが対応しておきました。

歩く&ラジコン操作

3D空間上をWASDキーで歩くことが出来ます。ただ、これはA-Frameはデフォルトで歩けるようになっています。しかし今回ラジコンもWASDキーで操作できるようにしたかったため、下記の様なUIを用意してクリックで操作を切り替えることができるようにしておきました。

下記のような感じで普通にクリックイベントでコンポーネントを取得してコンポーネントのメソッドを呼び出しています。

  selectCamera() {
    this.getCar().setKeyboardEnabled(false)
    this.getCamera().setKeyboardEnabled(true)
  }

  selectCar() {
    this.getCar().setKeyboardEnabled(true)
    this.getCamera().setKeyboardEnabled(false)
  }

  private getCamera(): MobileCameraControl {
    return document.querySelector('a-camera').components[
      'mobile-camera-control'
    ]
  }

  private getCar(): Car {
    return document.querySelector('[car]').components.car
  }

Vue.jsと共存

A-Frameはa-sceneという要素があれば3D空間を作ってくれますが、その外に普通のHTMLも書くことが出来ます。前述のUIもそのようにして作成しています。(VRモードでは見えないのであくまでもVR非対応端末用)

ただ、a-sceneがbody直下にないと今度は単なる3D描画だけになりVRボタンが消えてしまいますので、下記のようにしてシーンとHTMLのUIを分けて描画しています。

new Vue({
  render: h => h(Scene)
}).$mount('#scene')

new Vue({
  render: h => h(App)
}).$mount('#app')
index.html
  <body>
    <div id="scene"></div>
    <div id="app"></div>
  </body>

スマホ用移動ボタン

スマホ表示の場合は下記のようなボタンを表示し、タップでVR空間内を歩けるようにしています。そのうちラジコンも操作できるように改良したいです。

これも先程のようにカメラコンポーネントを取得してメソッドを呼び出して動かしているだけです。状態を変更して常時呼ばれ続けるtick内で動かしているだけです。

  tick() {
    if (this.up) {
      this.goUp()
    }
    if (this.down) {
      this.goDown()
    }
    if (this.left) {
      this.goLeft()
    }
    if (this.right) {
      this.goRight()
    }
  },
  goUp() {
    const angle = (Math.PI * this.el.getAttribute('rotation').y) / 180
    const position = this.el.getAttribute('position')
    position.x -= speed * Math.sin(angle)
    position.z -= speed * Math.cos(angle)
    this.el.setAttribute('position', position)
  },

デプロイ

基本的にHTML & JavaScriptだけでサーバーサイドの機能も不要なペライチページのため、Netlifyにデプロイしています。Gitでpushするだけです。

まとめ

こんな感じでVRポートフォリオを作ってみました。A-Frameはほんとにとりあえずプログラム無しのHTML1枚からVRコンテンツ作成を初められるので非常におすすめです。特にOculusストアにアプリを出すのは今のところ簡単ではなさそうですので、作ったアプリを一般公開するのは現在ある意味WebVR以外無いような状況でもあると思いますので非常に便利です。是非みなさんも試してみてください。

下記が今回実際に作ったVRポートフォリオです。よろしければ遊んでみてください。

面白いなと思う部分があったらぜひ「いいね」をお願いします!

VRポートフォリオ

dala00
Qiitaのようだけどポエムでも何でも書けるサービスを運営しています。 https://crieit.net 個人開発もしてるWebエンジニアです。業務依頼、同業種の方からのコンタクトなどお気軽に。業務経験有:PHP, MySQL, Laravel, Vue.js, Go, RoR 趣味サービス:Flutter, React, Next.js, Nuxt.js, Phoenix等色々
https://crieit.net/users/dala00
admin-guild
「Webサービスの運営に必要なあらゆる知見」を共有できる場として作られた、運営者のためのコミュニティです。
https://admin-guild.slack.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした