<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="http://organizeseries.com/"
	>

<channel>
	<title>原一浩 &#8211; HTML5Experts.jp</title>
	<atom:link href="/karad5/feed/" rel="self" type="application/rss+xml" />
	<link>https://html5experts.jp</link>
	<description>日本に、もっとエキスパートを。</description>
	<lastBuildDate>Sat, 07 Jul 2018 03:14:05 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.19</generator>
	<item>
		<title>React VRでここまでできる！VRでジオラマを作ろう</title>
		<link>/karad5/23960/</link>
		<pubDate>Mon, 31 Jul 2017 01:30:45 +0000</pubDate>
		<dc:creator><![CDATA[原一浩]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[React VR]]></category>
		<category><![CDATA[VR]]></category>

		<guid isPermaLink="false">/?p=23960</guid>
		<description><![CDATA[連載： React VR (4)前回、3Dプリミティブオブジェクトを使って、レイアウトやライティングの仕方について一通り試しました。前回扱わなかったコンポーネントに、3DモデルのためのコンポーネントModelがあります。...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/react-vr/" class="series-453" title="React VR" data-wpel-link="internal">React VR</a> (4)</div><div id="attachment_23961" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/HelloDiorama-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23961" srcset="/wp-content/uploads/2017/07/HelloDiorama.png 640w, /wp-content/uploads/2017/07/HelloDiorama-300x162.png 300w, /wp-content/uploads/2017/07/HelloDiorama-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">今回は、こんなVRジオラマをつくるぞ！</p></div>

<p>前回、3Dプリミティブオブジェクトを使って、レイアウトやライティングの仕方について一通り試しました。前回扱わなかったコンポーネントに、3Dモデルのためのコンポーネント<code>Model</code>があります。<code>Model</code>コンポーネントを使うと「obj」形式の3Dモデリングデータを読み込み、VR空間に配置することができます。</p>

<p>3Dのモデリングデータを使うと、リアルな物体だったり、複雑な形状を持ったオブジェクトを自由にVR上で扱えるため、VR空間における表現力が飛躍的に高まります。実際VRコンテンツを作る際に使うのは<code>Box</code>や<code>Cylinder</code>ではなく、<code>Model</code>コンポーネントになるでしょう。</p>

<p>今回は、3Dのモデリングデータを読み込み、ジオラマを作ってみましょう。子どもの頃、作ったプラモデルに顔を近づけて遊んだ経験はないでしょうか。VRでは、巨大な物体を目の前に表示させるのもお手のものです。</p>

<h2>新規プロジェクトの作成</h2>

<p>既に本連載の読者であれば何度か行ってきていることですが、今回もサンプルを作るにあたって新規プロジェクトを作成し、プロジェクトディレクトリへ移動します。<code>HelloDiorama</code>というプロジェクト名で進めることにします。</p>

<p></p><pre class="crayon-plain-tag">$ react-vr init HelloDiorama
$ cd HelloDiorama</pre><p></p>

<p>ジオラマに必要なものは何でしょうか? 一つは飾る対象物です。これはロボットなのかもしれないし、戦車かもしれないし、船かもしれません。3Dモデリングデータさえあれば、そしてそれをReact VRで読み込めさえすれば、なんでもジオラマにすることができます。</p>

<p>ちなみに「React VRで読み込めさえすれば」と書いているのは、Webで公開されている3Dモデリングデータの中には何故か表示できないものがあります。表示はできるけど変な形状になったりするものもあります。これはきっと時間と共に解決されていくタイプのものでしょう。気になることがあればReact VRのGitHubリポジトリでIssueを立てるとよいです。</p>

<p>続いてジオラマに必要なもう一つのものは何でしょう? それは雰囲気を与えてくれる背景です。緻密なモデルをさらに引き立ててくれる背景は、ロボットなら宇宙船の内部かもしれないし、船なら海上かもしれません。こちら背景は、今回は3Dプリミティブオブジェクトを利用してそれっぽいものを作ってみます。</p>

<h2>用意するもの</h2>

<p>ジオラマコンテンツを作るにあたって、用意するものは以下となりました。</p>

<ul>
<li>配置する対象物としての3Dモデリングデータ</li>
<li>背景の壁と床のテクスチャ</li>
</ul>

<p>まずは、配置する対象物としての3Dモデリングデータから用意しましょう。</p>

<div id="attachment_23962" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/GAZ-AA-640x350.png" alt="" width="640" height="350" class="size-large wp-image-23962" srcset="/wp-content/uploads/2017/07/GAZ-AA.png 640w, /wp-content/uploads/2017/07/GAZ-AA-300x164.png 300w, /wp-content/uploads/2017/07/GAZ-AA-207x113.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">1930年代に使われたソ連製のトラックのモデルデータ</p></div>

<p>今回ジオラマとして、シーンに配置するのは、<a href="https://ja.wikipedia.org/wiki/GAZ-AA" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">GAZ-AA</a>という1930年代に使われたソ連製のトラックにしてみました。筆者は、このトラックを好きだったわけではないですが、様々な3Dモデルを探す中でふとこのトラックを見かけ、素朴な中にも車両全面に漂う気品を魅力に感じ、採用した次第です。</p>

<p>このトラックは、ポリゴン数が4,380と、そこそこ複雑な形状をしており、テクスチャなどを含んでいてなかなかにリアリティがあります。</p>

<p>下記より、objフォーマット形式のものをダウンロードしましょう。もし他の3Dデータで試す場合、ライセンスについてチェックしておきましょう。</p>

<ul>
<li><a href="https://www.cgtrader.com/free-3d-models/vehicle/truck/gaz-aa-furgon-bread" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">GAZ- AA furgon-Bread free VR / AR / low-poly 3D Model MAX OBJ 3DS FBX MTL</a></li>
</ul>

<p>ちなみに、上記ダウンロードサイトでは、ユーザー登録が必要です。なので、ほかのものを用意できる人は好きな3Dデータを利用してOKです。「gaz-aa_bread OBJ.zip」をダウンロード、解凍したら、下記のディレクトリにそれぞれ配置します。</p>

<ul>
<li>static_assets/gaz_aa/gaz-aa_bread.mtl</li>
<li>static_assets/gaz_aa/gaz-aa_bread.obj</li>
<li>static_assets/gaz_aa/gaz-aa_bread_cabin.jpg</li>
<li>static_assets/gaz_aa/gaz-aa_bread_detail.jpg</li>
<li>static_assets/gaz_aa/gaz-aa_bread_frame.jpg</li>
<li>static_assets/gaz_aa/gaz-aa_bread_furgon.jpg</li>
<li>static_assets/gaz_aa/gaz-aa_bread_wheel.jpg</li>
<li>static_assets/gaz_aa/gaz-aa_bread_wing.jpg</li>
</ul>

<p>上記ファイルのうち、実は「gaz-aa_bread.mtl」については変更する必要があります。</p>

<p>テキストエディタなどでファイルを開き、「D:\Program Files\Autodesk\3ds Max 2009\scenes\GAZ-AA free models\gaz-aa_bread_3ds_max&#42;<strong>.jpg」となっているところを「</strong>*.jpg」に書き換えましょう。これはきっと作ったときそのままのローカルのパスが入ってしまったのですね。公開する際の要注意ポイントと言えそうです。</p>

<p>ジオラマの背景に必要な素材は、角となる2面分の壁用のテクスチャと、床に使うテクスチャです。前回使った<code>Pano</code>コンポーネントで、6面にテクスチャを貼り、部屋状にしてしまうこともできますが、それだとリアルな空間になりすぎ、ジオラマっぽくなくなるからです。3面しか壁を用意しないことで、後ろには漆黒の空間が広がる感じになり、なんだか超現実的な世界になります。</p>

<div id="attachment_23963" style="width: 310px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/wall-300x169.jpg" alt="" width="300" height="169" class="size-medium wp-image-23963" srcset="/wp-content/uploads/2017/07/wall-300x169.jpg 300w, /wp-content/uploads/2017/07/wall.jpg 640w, /wp-content/uploads/2017/07/wall-207x116.jpg 207w" sizes="(max-width: 300px) 100vw, 300px" /><p class="wp-caption-text">背景の壁のテクスチャ</p></div>

<div id="attachment_23964" style="width: 310px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/floor-300x169.jpg" alt="" width="300" height="169" class="size-medium wp-image-23964" srcset="/wp-content/uploads/2017/07/floor-300x169.jpg 300w, /wp-content/uploads/2017/07/floor.jpg 640w, /wp-content/uploads/2017/07/floor-207x116.jpg 207w" sizes="(max-width: 300px) 100vw, 300px" /><p class="wp-caption-text">床のテクスチャ</p></div>

<p>壁と床のテクスチャは以下からダウンロードしてください。</p>

<ul>
<li><a href="https://html5experts.jp/wp-content/uploads/2017/07/diorama.zip" data-wpel-link="internal">diorama</a></li>
</ul>

<p>ちなみに、壁と床のテクスチャは、僕がそのへんで適当に撮ってきたものなので、フリーでお使いいただいて構いません。</p>

<p>ダウンロードしたら、「プロジェクトディレクトリ/static_assets/diorama」以下に「floor.jpg」と「wall.jpg」を配置しましょう。</p>

<h2>STEP 1. まずは、ジオラマのベースづくりから</h2>

<p>早速トラックを配置したいと、はやる気持ちを抑えてまずはジオラマのベースとなる背景の壁と床を作るところから始めましょう。床は、1000 x 1000の大きさを持った板を想定しました。これは、<code>Pano</code>コンポーネントで作った空間と同じ大きさとなります。そして、奥の壁は床から500の高さを持つ平面です。これにテクスチャをつけることで、リアリティを持たせます。では、具体的な作業をしましょう。</p>

<p>「index.vr.js」の<code>View</code>の中を一旦空にし、下記のように修正します。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
              &lt;View
                      style={{
                        transform: [
                          {rotateY: -20},
                        ]
                      }}&gt;
                &lt;Plane
                        dimWidth={1000}
                        dimHeight={500}
                        style={{
                          transform: [
                            {translate: [-500, 220, 0]},
                            {rotateY: 90},
                          ],
                        }}
                        texture={asset('diorama/wall.jpg')}
                /&gt;
                &lt;Plane
                        dimWidth={1000}
                        dimHeight={500}
                        style={{
                          transform: [
                            {translate: [0, 220, -500]},
                          ],
                        }}
                        texture={asset('diorama/wall.jpg')}
                /&gt;
                &lt;Plane
                        dimWidth={1000}
                        dimHeight={1000}
                        style={{
                          transform: [
                            {translate: [0, -22, 0]},
                            {rotateX: -90},
                          ],
                        }}
                        texture={asset('diorama/floor.jpg')}
                /&gt;
              &lt;/View&gt;
            &lt;/View&gt;</pre><p></p>

<p>それと、importも変更しておきましょう。この先に使う<code>Model</code>コンポーネントやライティング関係のコンポーネントも加えておきます。</p>

<p></p><pre class="crayon-plain-tag">import {
  AppRegistry,
  asset,
  View,
  Plane,
  Model,
  DirectionalLight,
  PointLight,
  AmbientLight,
} from 'react-vr';</pre><p></p>

<p><code>View</code>コンポーネントが入れ子になっているのは、内側の<code>View</code>は、ジオラマの背景セットで、セット全体を変形させたい場合はこのように入れ子にしておくと、壁や床を一つの塊として扱えます。ここではジオラマのセット全体をちょっと回転させています。というのも、最初に表示したときに部屋の中央ではなく、部屋の角を見せたいためです。</p>

<p>ジオラマのセット自体を回転させずに、カメラを回転させるという表現方法もありますが、普通ジオラマというのは、インテリアの側面もあり、一番かっこいいポジションで飾るものだと思います。そこで、<code>View</code>自体をY軸に対して-20度回転させました。</p>

<p>さらに細部を見ていきましょう。3つの<code>Plane</code>が、内側の<code>View</code>コンポーネント内に配置されていますが、先頭2つの<code>Plane</code>コンポーネントは壁として配置してあります。位置を遠くに置いたのと、Y軸方向に90度回転させて垂直にそれぞれのコンポーネントが交わるようにしています。</p>

<p><code>Plane</code>コンポーネントに関わらず、3Dプリミティブコンポーネントは、テクスチャを設定することができます。テクスチャは<code>texture</code>属性で設定します。</p>

<p>ここでは<code>texture</code>属性に、「diorama/wall.jpg」を指定しました。これによりのっぺりとした壁が質感のある壁となりました。ちなみに、この壁は近くの公園の壁を撮影したものです。</p>

<p>一番最後の<code>Plane</code>は、床として配置しています。X軸方向に-90度回転させ、テクスチャを貼りました。これは海に行った時の砂岩の岩肌です。深い意味があるわけではないですが、オフロードっぽい印象になる写真が見つからなかったので、こちらを採用しました。</p>

<p></p><pre class="crayon-plain-tag">$ npm start</pre><p></p>

<p>を実行し、ブラウザでURLを開いてみましょう。ただし、こんどは「http://localhost:8081/vr/?hotreload」で開いてみてください。「?hotreload」を付けてブラウザから開くと、ホットリロードが可能になります。これで、エディタで編集したコンテンツが自動でブラウザ側に反映されるようになります。</p>

<div id="attachment_23966" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/HelloDiorama_base-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23966" srcset="/wp-content/uploads/2017/07/HelloDiorama_base.png 640w, /wp-content/uploads/2017/07/HelloDiorama_base-300x162.png 300w, /wp-content/uploads/2017/07/HelloDiorama_base-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">配置した背景</p></div>

<p>3方向のみ<code>Plane</code>を配置しただけの簡素なジオラマセットですが、VRで角のほうを見るとなかなかどうして迫力がありますね。</p>

<h2>STEP 2. 3Dモデリングデータを配置しよう!</h2>

<p>続いて、お待ちかねの3Dモデルの読み込みです。3Dモデリングデータの読み込みには、<code>Model</code>コンポーネントを使います。<code>Model</code>コンポーネントには、<code>source</code>属性を記述することができます。渡す内容は、<code>obj</code>と<code>mtl</code>というキーを持ったオブジェクトで、それぞれobj形式のファイルとmtl形式のファイルへのパスを渡します。</p>

<p>今回であれば、「配置するモデリングデータ」で保存しておいた「static_assets/gaz_aa」以下にあるobjファイルとmtlファイルが対象になります。</p>

<p><code>Model</code>コンポーネントは、「index.vr.js」の入れ子の内側の<code>View</code>以下に配置します。サイズは小さめにし、位置調整と<code>rotateY</code>プロパティを修正して、若干の回転を加えます。これは、ちょうど左前に向いた形がきれいだからです。コードは下記のようになります。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
              &lt;View
                      style={{
                        transform: [
                          {rotateY: -20},
                        ]
                      }}&gt;
                &lt;Model
                        style={{
                          transform: [
                            {translate: [-30, -20, -110]},
                            {scale: 0.03},
                            {rotateY: 70},
                          ],
                        }}
                        source={{
                          obj: asset('gaz_aa/gaz-aa_bread.obj'),
                          mtl: asset('gaz_aa/gaz-aa_bread.mtl')
                        }}
                        lit={true}
                /&gt;
                &lt;Plane ... /&gt;
                &lt;Plane ... /&gt;
                &lt;Plane ... /&gt;
              &lt;/View&gt;
            &lt;/View&gt;</pre><p></p>

<p>これで、ブラウザをリロードしてみてください。3Dモデルが表示されるはずです。</p>

<div id="attachment_23967" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/HelloDiorama_black-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23967" srcset="/wp-content/uploads/2017/07/HelloDiorama_black.png 640w, /wp-content/uploads/2017/07/HelloDiorama_black-300x162.png 300w, /wp-content/uploads/2017/07/HelloDiorama_black-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">まだ光が当たっていないので真っ黒</p></div>

<p>ただし、真っ黒なシルエットになってしまっていますが。ということで、続いて光源を用意して、明るくしていきましょう。</p>

<h2>STEP 3. ライティングしてトラックを美しく!</h2>

<p>ライティングは、前回3Dプリミティブオブジェクトで遊んだ際に試したのを思い出してください。メインの明かり、部分的な明かり、ちょっとした調整です。今回も同じような感じで進めます。</p>

<p>実は、React VRで使われている3DライブラリのThree.js本体には、ライティングに関する様々なヘルパー機能が用意されています。例えば、照明の向き、範囲などを視覚的に表示して微調整をする機能などです。ただ、現時点のReact VRではもっと限定的なサポートとなっているのでそこまで細かくは扱いません。</p>

<p>「index.vr.js」に<code>DirectionalLight</code>と<code>PointLight</code>、<code>AmbientLight</code>コンポーネントを配置しました。これで、トラックが綺麗に表示されるでしょうか。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
              &lt;DirectionalLight
                      intensity={0.3}
                      style={{
                        color: 'white',
                        transform: [
                          {translate: [0, 0, 0]},
                          {rotateX: 45}]
                      }}/&gt;
              &lt;PointLight
                      intensity={0.5}
                      style={{
                        color: 'white',
                        transform: [{translate: [50, 20, -80]}]
                      }}/&gt;
              &lt;AmbientLight
                      intensity={0.8}/&gt;
              &lt;View ... /&gt;
            &lt;/View&gt;</pre><p></p>

<div id="attachment_23968" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/HelloDiorama_3d_model-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23968" srcset="/wp-content/uploads/2017/07/HelloDiorama_3d_model.png 640w, /wp-content/uploads/2017/07/HelloDiorama_3d_model-300x162.png 300w, /wp-content/uploads/2017/07/HelloDiorama_3d_model-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">トラックがちゃんと表示された！</p></div>

<p>ブラウザをリロードしてトラックを再表示してみましょう。明るくなったでしょうか。</p>

<h2>STEP 4. トラックをゆっくりと回転させてみる</h2>

<p>以上で一旦はジオラマは完成しましたと言ってもいいかもしれません。ただ、今まで物体を空間に置いてみて歯がゆかったのは、その物体の裏側がどうなっているのか、それが見えないということでした。ということで、アニメーションの練習がてらトラックを回転させてみましょう。</p>

<p>回転に関しては、ピッタリのサンプルが公式のリポジトリに用意されています。</p>

<ul>
<li><a href="https://github.com/facebook/react-vr/tree/master/Examples/ModelSample" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">react&#45;vr/Examples/ModelSample at master · facebook/react&#45;vr</a></li>
</ul>

<p>このサンプルを参考にトラックのアニメーションを作ってみます。ちょっとサンプルと異なるのは、Reactのコンポーネントとして作るというのと、細かなロジックを修正した点です。Reactコンポーネントとして、回転速度を定義する<code>speed</code>属性と、表示位置や大きさを定義する<code>style</code>属性を渡せるように作っておきましょう。「src/component/GazAa.js」として下記のように作成します。ちょっと長くなるので、細部の話は置いておいて、まずは一気に掲載してしまいます。</p>

<p></p><pre class="crayon-plain-tag">import React from 'react';
import {
  asset,
  View,
  Model,
} from 'react-vr';

export default class GazAa extends React.Component {

  constructor() {
    super();
    this.state = {
      rotation: 0
    };
  }

  componentDidMount() {
    this.rotate();
  }

  componentWillUnmount() {
    if (this.frameHandle) {
      cancelAnimationFrame(this.frameHandle);
      this.frameHandle = null;
    }
  }

  rotate(timestamp) {
    const delta = timestamp - this.lastUpdate || 0;
    this.setState({rotation: this.state.rotation + delta / this.props.speed});
    this.lastUpdate  = timestamp;
    this.frameHandle = requestAnimationFrame(this.rotate.bind(this));
  }

  render() {
    return (&lt;View style={this.props.style}&gt;
              &lt;Model
                      style={{
                        transform: [
                          {rotateY: this.state.rotation},
                        ]
                      }}
                      source={{
                        obj: asset('gaz_aa/gaz-aa_bread.obj'),
                        mtl: asset('gaz_aa/gaz-aa_bread.mtl')
                      }}
                      lit={true}
              /&gt;
            &lt;/View&gt;
    )
  }
}</pre><p></p>

<p>ポイントは、<code>GazAa</code>コンポーネントのローカルステートとそれを変更するためのrotate関数、そしてそこで使われている<code>requestAnimationFrame</code>関数と<code>cancelAnimationFrame</code>関数です。</p>

<p><code>GazAa</code>コンポーネントは、シーンに配置した瞬間、つまりコンポーネントがマウントされた時から回転を始めます。逆にコンポーネントをアンマウントすると回転をやめる処理をします。回転の状態はコンポーネントのローカルステートとして定義されている<code>rotation</code>です。</p>

<p><code>rotation</code>は、3Dモデルの<code>rotateY</code>としてY軸方向にどれだけ回転するかという値として使われることになります。その値をコントロールしているのが<code>rotate</code>関数です。<code>requestAnimationFrame</code>関数は、ブラウザの再描画のタイミングで<code>rotate</code>関数を呼び出すことになるので、呼び出すたびに前に呼び出された時間からの回転を<code>rotation</code>に反映していきます。<code>requestAnimationFrame</code>関数から返った値は、アニメーションをキャンセルするときに<code>cancelAnimationFrame</code>関数にて使われます。</p>

<p><code>requestAnimationFrame</code>関数について一つ知っておきたいことは、この関数はもともとブラウザに実装されていますが、ブラウザによってはサポートされていないことがあります。そこで、React VRでは、<code>requestAnimationFrame</code>関数のpolyfillとして用意されています。</p>

<p>これで大体の<code>GazAa</code>コンポーネントの仕組みが理解できたでしょうか。今はこういうスタイルでアニメーションを実現したりしますが、将来的にはもっと洗練されたアニメーション機構が用意されていくのだろうと推測します。</p>

<p>では、先ほど作った<code>GazAa</code>コンポーネントを使っていきましょう。「index.vr.js」で使うので、まずはインポートします。ファイルの先頭あたりにimport文を書きます。</p>

<p></p><pre class="crayon-plain-tag">import GazAa from './src/component/GazAa'</pre><p></p>

<p>続いて、入れ子になった<code>View</code>コンポーネントの内側に、<code>GazAa</code>コンポーネントを配置します。プロパティとしては、回転速度を定義する<code>speed</code>属性と、表示位置や大きさを定義する<code>style</code>属性を渡しています。これら属性は、<code>GazAa</code>コンポーネント内の<code>this.props.XXX</code>にて受け取ることが可能です。これらを記載したコードが以下になります。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
              &lt;DirectionalLight ... /&gt;
              &lt;PointLight ... /&gt;
              &lt;AmbientLight ... /&gt;
              &lt;View
                      style={{
                        transform: [
                          {rotateY: -20},
                        ]
                      }}&gt;
                {/* &lt;Model ... /&gt; */}
                &lt;GazAa speed={360}
                       style={{
                         transform: [
                           {translate: [-42, -20, -110]},
                           {scale: 0.03},
                         ],
                       }}/&gt;
                &lt;Plane ... /&gt;
                &lt;Plane ... /&gt;
                &lt;Plane ... /&gt;
              &lt;/View&gt;
            &lt;/View&gt;</pre><p></p>

<p>以上で、トラックが回転するジオラマの完成です。ブラウザをリロードして、じっくり見てみましょう！</p>

<div id="attachment_23961" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/HelloDiorama-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23961" srcset="/wp-content/uploads/2017/07/HelloDiorama.png 640w, /wp-content/uploads/2017/07/HelloDiorama-300x162.png 300w, /wp-content/uploads/2017/07/HelloDiorama-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">完成したVRジオラマ</p></div>

<p>もし興味があれば、<a href="https://html5experts.jp/karad5/23885/" data-wpel-link="internal">React VR×360度画像！Web上でパノラマVR表示を試す</a>を参考に、GearVRで眺めてみましょう。子供の頃叶わなかった、巨大サイズのジオラマを見ることができますよ。</p>
]]></content:encoded>
		
		<series:name><![CDATA[React VR]]></series:name>
	</item>
		<item>
		<title>Reactといえばコンポーネント！React VRの3Dプリミティブコンポーネントを探る、触る</title>
		<link>/karad5/23945/</link>
		<pubDate>Mon, 24 Jul 2017 01:00:05 +0000</pubDate>
		<dc:creator><![CDATA[原一浩]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[GearVR]]></category>
		<category><![CDATA[React VR]]></category>
		<category><![CDATA[WebVR]]></category>

		<guid isPermaLink="false">/?p=23945</guid>
		<description><![CDATA[連載： React VR (3)前回、React VRでパノラマ写真を見るというコンテンツを作成しました。 サンプルを試していただいた方は「なんか結構できたじゃん感」を満喫できたと思います。それもそのはず、360度写真の...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/react-vr/" class="series-453" title="React VR" data-wpel-link="internal">React VR</a> (3)</div><div id="attachment_23947" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23947" srcset="/wp-content/uploads/2017/07/Hello3DObject2_AmbientLight.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">今回のサンプルの完成版。ライティングとかもやるぞ</p></div>

<p><a href="https://html5experts.jp/karad5/23885/" target="_blank" data-wpel-link="internal">前回</a>、React VRでパノラマ写真を見るというコンテンツを作成しました。<br />
サンプルを試していただいた方は「<strong>なんか結構できたじゃん感</strong>」を満喫できたと思います。それもそのはず、360度写真のみのコンテンツは、天球にパノラマ画像を貼り付けた時点で、目的の99%を達成できたといえるからです。ほとんど完成といっていい状態でしょう。</p>

<p>しかし、他のVRコンテンツを触ったことがある人間なら、少しもの足りなさを感じることと思います。一つは<strong>インタラクティブ性のなさ</strong>、そしてもう一つは<strong>モノの存在感のなさ</strong>です。</p>

<p>インタラクティブ性のなさは、イベント駆動型のVRコンテンツの作成というハードルが待っていますが、今回はそれはさておき、モノの存在感について書いていきます。</p>

<p>パノラマ画像だけで構成された世界は、「<strong>一見、目の前で展開されている感じなのに、触ることができないほど遠くに広がる世界</strong>」と言えます。目の前の芝生に近付いて触ることはできませんし、奥の人に近付くこともできません。</p>

<p>仮に頑張って、インタラクティブ性を高めて奥に進めるように作ったとしても、そこにあるのは<strong>拡大されて画素が粗くなった人のようなナニカ</strong>でしかありません。</p>

<p>VRのモノとしての存在を確固たるものにするために大事なことは、VR空間に実際にモノを置いてみるということになります。</p>

<p>ということで、今回はReact VRに用意されているコンポーネントのうち、モノとして置けるコンポーネント、3Dプリミティブについて扱っていきます。</p>

<h2>いろいろなタイプのReact VR Components</h2>

<p><a href="https://facebook.github.io/react-vr/docs/getting-started.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">公式ドキュメント</a>にあるReact VR Componentsの目次は下記のような構成になっています。</p>

<ul>
<li>AmbientLight</li>
<li>Box</li>
<li>LiveEnvCamera</li>
<li>Cylinder</li>
<li>CylindricalPanel</li>
<li>DirectionalLight</li>
<li>Model</li>
<li>Pano</li>
<li>Plane</li>
<li>PointLight</li>
<li>Scene</li>
<li>Sound</li>
<li>Sphere</li>
<li>SpotLight</li>
<li>Video</li>
<li>VideoControl</li>
<li>VideoPano</li>
<li>VrButton</li>
</ul>

<p>いろいろありますね。「<strong>あれ?、これだけしかないの?</strong>」という見方もあるかもしれません。主要なものを役割ごとにカテゴライズしてみましたので順に見ていきましょう。各種コンポーネントの実装コードに興味がある方は、<a href="https://github.com/facebook/react-vr/tree/master/ReactVR/js/Views" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">GitHubのReact VRリポジトリのViews以下</a>を見てみるとよいでしょう。</p>

<h3>空間を作るタイプのコンポーネント</h3>

<p>まず、チェックしておきたいのは空間を作るタイプのコンポーネントです。</p>

<ul>
<li>VideoPano</li>
<li>CylindricalPanel</li>
<li>Pano</li>
</ul>

<p><code>Pano</code>は、既に登場しましたが、360度写真をVR空間に貼り付けるタイプのコンポーネントです。</p>

<p><code>VideoPano</code>は、Panoと同様ですが、貼り付け可能コンテンツが360度動画となります。<code>CylindricalPanel</code>は、ちょっと特殊なコンポーネントで、内側にテクスチャを貼ることができ、子コンポーネントを収録できるタイプです。今回は触れません。</p>

<h3>ビデオ・オーディオ関連のコンポーネント</h3>

<p>ビデオの話が少し出ましたが、ビデオ・オーディオ系に関係してくるコンポーネントは以下となります。</p>

<ul>
<li>Sound</li>
<li>Video</li>
</ul>

<p><code>Sound</code>は、シーンに配置するコンポーネントですが、何か形があるわけではありません。音の発生源として配置する形になります。3Dオーディオをサポートしており、ヘッドマウントディスプレイを被って顔を左右に振ったりすると、音源の場所に応じたサウンドになることが確認できます。</p>

<p><code>Video</code>は、2Dのビデオを再生するためのコンポーネントです。これをユーザーの前面に貼ると巨大なテレビが目の前に広がったような演出ができます。</p>

<h3>ユーザーインターフェースとなるコンポーネント</h3>

<p>続いて、VR世界のユーザーインターフェースとなるコンポーネントが下記2つです。</p>

<ul>
<li>VrButton</li>
<li>VideoControl</li>
</ul>

<p><code>VrButton</code>は、ボタンです。応用性が高く、使い勝手の良いコンポーネントと言えるでしょう。<code>VideoControl</code>は、ビデオをコントロールするためのユーザーインターフェースとなります。
<code>Video</code>コンポーネントと<code>VideoControl</code>コンポーネントを組み合わせると、VR空間にビデオプレーヤーを作ることができます。</p>

<div id="attachment_23948" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/ReactVR_video-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23948" srcset="/wp-content/uploads/2017/07/ReactVR_video.png 640w, /wp-content/uploads/2017/07/ReactVR_video-300x162.png 300w, /wp-content/uploads/2017/07/ReactVR_video-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">Videoコンポーネントでビデオを表示させているサンプル</p></div>

<h3>形状コンポーネント</h3>

<p>そして、今回扱う形状コンポーネントです。</p>

<ul>
<li>Box</li>
<li>Cylinder</li>
<li>Plane</li>
<li>Sphere</li>
<li>Model</li>
</ul>

<p>上記のうち、Modelを除いた4つは<strong>3Dプリミティブコンポーネント</strong>と呼ばれます。<code>Box</code>は立方体や直方体などを作成することができるタイプのコンポーネントです。<code>Cylinder</code>は、円筒形の形状コンポーネントで、設定によっては円錐形の形状を作成することができます。<code>Plane</code>は、フラットな平面コンポーネントです。</p>

<p>ちなみに、<code>Model</code>は空間に配置するコンポーネントだけど、別の3Dソフトなどで作成したモデルデータを使用するためのもので、今回は一旦スキップします。</p>

<p>これ以外にもライティングに関するコンポーネントも存在しますが、実際に使うところで解説していきます。</p>

<p>では、今回は実際に3Dプリミティブコンポーネントを、シーンにいろいろと配置し、様々なライティングをしてみましょう。</p>

<h2>3Dプリミティブコンポーネントを配置してみよう</h2>

<p>さて、これから3Dプリミティブコンポーネントを配置していろいろ実験していくわけですが、その前に、何か仮想現実の実験ぽくするための会場づくりをしましょう。React VRで何も背景に敷かない場合、漆黒の空間に単なる立方体が浮かぶことになります。それでは何も趣がないですよね。</p>

<p>ということで、<strong>VR空間をホロデッキ（アメリカのTVドラマ・映画のスタートレックに登場するホログラフィックルーム）として定義</strong>してみましょう。ホロデッキってなあに？って方は、Wikipediaの<a href="https://en.wikipedia.org/wiki/Holodeck" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ホロデッキに関する説明と写真</a>をご覧ください。</p>

<p>ホロデッキは、黒い部屋に、方眼紙のような感じで黄色の線が入っている部屋です。これを実現するために<code>Pano</code>コンポーネントを使います。<code>Pano</code>コンポーネントは360度写真を閲覧するために前回使いましたが、<code>Pano</code>コンポーネントはもう一つ使い方があって、6つのテクスチャを配列で渡してあげると、立方体のの内側にテクスチャが貼られた部屋を作ることができます。</p>

<p>では、まず新規React VRプロジェクトを作成するところから始めてみましょう。</p>

<h3>1. 新規React VRプロジェクトを作成し、Panoコンポーネントで部屋を作る</h3>

<p>まずはなにはともあれ、新規ReactVRプロジェクトを立ち上げましょう。名前は<code>Hello3DObject</code>としましょう。</p>

<p></p><pre class="crayon-plain-tag">$ react-vr init Hello3DObject
$ cd Hello3DObject</pre><p></p>

<p>続いて、<code>Pano</code>コンポーネントを使って、テクスチャが貼られた立方体の空間を作っていきます。プロジェクトルートにある「index.vr.js」の<code>View</code>コンポーネント以下を編集していきます。今回<code>Pano</code>コンポーネントの内側には、前後左右上下の6面にテクスチャを貼ります。貼るテクスチャは、<a href="http://www.premiumpixels.com/freebies/20-seamless-photoshop-grid-patterns/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">フリーのグリッドパターン &#8211; 20 Seamless Photoshop Grid Patterns</a>のうち一枚をPhotoShopで修正した格子状のものです。</p>

<div id="attachment_23950" style="width: 310px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/holodeck-300x300.png" alt="" width="300" height="300" class="size-medium wp-image-23950" srcset="/wp-content/uploads/2017/07/holodeck-300x300.png 300w, /wp-content/uploads/2017/07/holodeck-150x150.png 150w, /wp-content/uploads/2017/07/holodeck-207x207.png 207w, /wp-content/uploads/2017/07/holodeck.png 500w" sizes="(max-width: 300px) 100vw, 300px" /><p class="wp-caption-text">ホロデッキっぽいテクスチャ画像</p></div>

<ul>
<li><a href="https://html5experts.jp/wp-content/uploads/2017/07/holodeck.zip" data-wpel-link="internal">こちらからダウンロードください</a></li>
</ul>

<p>上記リンク先でダウンロードしたファイルを解凍し、中に入っている「holodeck.png」を「static_assets」ディレクトリ以下に配置します。</p>

<p><code>Pano</code>コンポーネントに対して六面にテクスチャを貼るには、<code>source</code>属性に<code>uri</code>プロパティを持ったオブジェクトを6つ含んだ配列を渡します。<code>asset</code>関数は、ファイル名を渡すと<code>{uri: パス名}</code>の形式で返るので、<code>asset</code>関数をそのまま<code>source</code>属性へ渡せばいいことになります。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
              &lt;Pano source={[
                asset('holodeck.png'), // 右
                asset('holodeck.png'), // 左
                asset('holodeck.png'), // 上
                asset('holodeck.png'), // 下
                asset('holodeck.png'), // 後
                asset('holodeck.png')  // 前
              ]}
              /&gt;
            &lt;/View&gt;</pre><p></p>

<p>さて、まずはここで一旦ビルドしてみましょう。</p>

<p></p><pre class="crayon-plain-tag">$ npm start</pre><p></p>

<p>ブラウザで、<code>http://localhost:8081/vr/</code>を開いてみましょう。スタートレックのホロデッキのような空間が出現したと思います。テクスチャのつなぎ目とか細かい点はサンプルということでご容赦ください。</p>

<div id="attachment_23949" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_holodeck-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23949" srcset="/wp-content/uploads/2017/07/Hello3DObject2_holodeck.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_holodeck-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_holodeck-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">ホロデッキに入った</p></div>

<h3>2. <code>Box</code>をいくつか並べて配置してみる</h3>

<p>ホロデッキ的な空間が出来たところで、<code>Box</code>コンポーネントを配置してみましょう。<code>Box</code>コンポーネントはシンプルなコンポーネントですが、よくありがちな失敗として、<code>Box</code>コンポーネントをインポートし忘れるということがあります。これから登場する<code>Cylinder</code>や<code>Sphere</code>も同様にimportし忘れがないようにしましょう。</p>

<p></p><pre class="crayon-plain-tag">import {
  AppRegistry,
  asset,
  Pano,
  Box,
  Cylinder,
  Sphere,
  View,
} from 'react-vr';</pre><p></p>

<p>では、<code>Box</code>コンポーネントを目の前に3つ配置してみます。<code>Pano</code>コンポーネントの下に<code>Box</code>コンポーネントを下記のように3つ記述します。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
                &lt;Pano ... /&gt; 
                &lt;Box dimWidth={0.5}
                     dimDepth={0.5}
                     dimHeight={0.5}
                     style={{
                       color: '#00f',
                       transform: [{translate: [1, 0, -2]}],
                     }}
                     lit={false}
                /&gt;
                &lt;Box dimWidth={0.3}
                     dimDepth={0.5}
                     dimHeight={1}
                     style={{
                       color: '#f00',
                       transform: [{translate: [0.2, 0, -2]}],
                     }}
                     lit={false}
                /&gt;
                &lt;Box dimWidth={0.7}
                     dimDepth={1}
                     dimHeight={0.3}
                     style={{
                       color: '#0f0',
                       transform: [{translate: [-0.7, 0, -2]}],
                     }}
                     lit={false}
                /&gt;
            &lt;/View&gt;</pre><p></p>

<p><code>dimWidth</code>、<code>dimHeight</code>、<code>dimDepth</code>の各属性は、幅、高さ、奥行きのサイズに相当します。この比率を変えることで、立方体や柱のようなもの、平らな板のようなものを作り出すことができます。</p>

<p>また、<code>style</code>属性で色が定義されていることもわかります。3つの色は右から青、赤、緑の原色です。<code>style</code>属性に<code>transform</code>というプロパティが定義されていますが、ここで配置を指定しています。位置関係の変形は、<code>translate</code>で指定します。配列で指定し、左からX座標、Y座標、Z座標となります。Z座標は奥行きです。ちなみにマイナスの数値になればなるほど初期状態の位置から奥へ向かって移動する形になります。</p>

<p><code>lit</code>という属性がありますが、こちらはライティングに関するプロパティで、後ほど解説します。</p>

<div id="attachment_23952" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_box-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23952" srcset="/wp-content/uploads/2017/07/Hello3DObject2_box.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_box-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_box-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">Boxコンポーネントを3つ配置した</p></div>

<p><code>Box</code>コンポーネントを配置できたところで、他のコンポーネントを配置していきましょう!</p>

<h3>3. <code>Box</code>だけでなく、<code>Cylinder</code>や<code>Sphere</code>を配置してみる</h3>

<p>さて、今度は<code>Cylinder</code>や<code>Sphere</code>もシーンに配置してみます。一旦<code>Box</code>コンポーネントのパートで作った3つのボックスは消してしまいましょう。勢いあまってホロデッキっぽくしている<code>Pano</code>まで消さないようにしてくださいね、情感がなくなってしまいますので。</p>

<p>まず、<code>Cylinder</code>コンポーネントについて。Cylinder、つまりカタカナでいうシリンダーは、円筒を意味しますが、<code>Cylinder</code>コンポーネントはプロパティ次第で円錐形にもなります。ポイントは<code>radiusTop</code>と<code>radiusBottom</code>で、<code>radiusTop</code>が小さければ山のようになっていき、<code>radiusBottom</code>が大きければ、ラッパのような形状になっていきます。どちらの値も等しい時だけ円筒形になります。</p>

<p>続いて<code>Sphere</code>コンポーネントですが、Sphereというのは球体です。<code>Sphere</code>コンポーネントはなかなか使い出があるコンポーネントで、四角形や円筒形を使う機会はそれほどないかもしれませんが、球体というのはテクスチャを貼り付ければ惑星になったりと応用性が高い3Dプリミティブコンポーネントです。下記のようにシーンに配置してみました。それぞれ一つずつ配置しています。<code>Sphere</code>コンポーネントには<code>widthSegments</code>と<code>heightSegments</code>というプロパティがありますが、これは球体を構成するセグメント（分割数）を定義しています。この数が増えるとなめらかな球体へ近づいていきます。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
                &lt;Pano ... /&gt; 
                &lt;Box dimWidth={0.3}
                     dimDepth={0.3}
                     dimHeight={0.3}
                     style={{
                       color: '#00f',
                       transform: [{translate: [0.5, -0.5, -1]}]
                     }}
                     lit={false}
                /&gt;
                &lt;Cylinder radiusTop={0.1}
                          radiusBottom={0.4}
                          dimHeight={0.8}
                          segments={20}
                          style={{
                            color: '#f00',
                            transform: [{translate: [-0.2, -1, -3]}],
                          }}
                          lit={false}
                /&gt;
                &lt;Sphere radius={0.3}
                        widthSegments={15}
                        heightSegments={15}
                        style={{
                          color: '#0f0',
                          transform: [{translate: [-2, -1, -5]}],
                        }}
                        lit={false}
                /&gt;
            &lt;/View&gt;</pre><p></p>

<p>今回、ちょっと配置に工夫をしています。<code>translate</code>プロパティの値を変更していて、手前に立方体、奥に行くにしたがって円筒形、球体と並ぶようにしています。これで3Dプリミティブの配置は完了したわけですが、何かもの足りません。のっぺりしていて立体感がないのです。ということで、この3Dオブジェクトに光を当てていきましょう。</p>

<div id="attachment_23953" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_three_obj-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23953" srcset="/wp-content/uploads/2017/07/Hello3DObject2_three_obj.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_three_obj-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_three_obj-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">配置された、球体、円錐形、立方体</p></div>

<h3>4. 3Dプリミティブオブジェクトに光を当ててみる</h3>

<p>React VRでライティング（照明）を行うには、用意されている4つのコンポーネントのいずれかもしくは複数の組み合わせを使用します。</p>

<p>用意されているReact VRコンポーネントは下記の4つです。</p>

<ul>
<li>AmbientLight</li>
<li>DirectionalLight</li>
<li>PointLight</li>
<li>SpotLight</li>
</ul>

<p><code>AmbientLight</code>は、<strong>環境光</strong>と呼ばれるもので、シーン全体に均一な影響を与える光源を定義します。これは無指向性で、すべてのオブジェクトが等しく明るくなります。</p>

<p><code>DirectionalLight</code>は、<strong>指向性があるが、距離による明かりの減光は発生しないタイプの光源</strong>です。太陽の明かりのようなものと言えます。</p>

<p><code>PointLight</code>は、<strong>ある一点から発生する光源</strong>で、距離による減光もあります。見えない間接照明のようなものと言えるでしょう。</p>

<p><code>SpotLight</code>は、文字通り<strong>スポットライトのような特性を持つととらえられる光源</strong>です。指向性があり、距離による範囲の拡大と減光があります。</p>

<p>20程度のコンポーネントしか用意されていないReact VRにおいて、ライティング関係だけで、4つもコンポーネントが用意されているのは、一つはVRにおいてそれだけ重要であるということと、React VRが使用しているThree.jsにおいても手厚いサポートがされていること、そしておそらくはこうしたライティング関係は、カスタムコンポーネントとしての作成が困難であろうことなどが推測されます。</p>

<p>まずは普通の光を当てましょう。太陽のように上から降り注ぐ普通の明かりです。こういった明かりは、<code>DirectionalLight</code>コンポーネントを使うことで実現できます。</p>

<p>では、まず準備段階として、先ほど作成した3種類の3Dプリミティブオブジェクトが持っている<code>lit</code>プロパティを<code>true</code>にしてみましょう。これで光源の影響を受けるようになります。試しに<code>true</code>にした段階で、ブラウザをリロードしてみてください。まだ光が当たっていないため、真っ黒のオブジェクトになってしまったと思います。</p>

<div id="attachment_23954" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_three_obj_black-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23954" srcset="/wp-content/uploads/2017/07/Hello3DObject2_three_obj_black.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_three_obj_black-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_three_obj_black-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">真っ黒の3Dプリミティブオブジェクト</p></div>

<p>続いて、<code>DirectionalLight</code>コンポーネントを配置します。<code>Pano</code>コンポーネントの下あたりでOKです。こんな感じにします。(importを忘れずに)</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
            &lt;Pano ... /&gt;
            {/* Lighting */}
            &lt;DirectionalLight   intensity={0.5}
                                style={{
                                color: 'white',
                                transform: [
                                    {translate: [0, 0, 0]},
                                    {rotateX: 45}]
                                }}/&gt;
            &lt;Box ... /&gt;
            &lt;Cylinder ... /&gt;
            &lt;Sphere ... /&gt;
        &lt;/View&gt;</pre><p></p>

<p><code>intensity</code>プロパティは、光の強度を設定します。また、光源にも色をつけることができ、スタイルシートで定義します。<code>transform</code>プロパティで<code>rotateX</code>の設定をしていますが、これは、ちょっと斜め前方から光を当てたいからです。本当の真上からあたる光は、側面すら陰になってしまい、あまり面白みはありません。</p>

<div id="attachment_23955" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_DirectionalLight-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23955" srcset="/wp-content/uploads/2017/07/Hello3DObject2_DirectionalLight.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_DirectionalLight-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_DirectionalLight-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">DirectionalLightを設定したシーン</p></div>

<p>次は<code>PointLight</code>コンポーネントを配置してみましょう。PointLightは点光源なので、任意の位置に配置すると、その周囲を照らしてくれます。うまく使うと印象的な効果を与えることができます。さて、今回は、PointLightをちょっと手前に配置し、しかもちょっと青系の光として照らしてみましょう。どんな感じになるでしょうか。</p>

<p><code>DirectionalLight</code>コンポーネントの下に、下記のように<code>PointLight</code>コンポーネントを設置します。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
            &lt;Pano ... /&gt;
            {/* Lighting */}
            &lt;DirectionalLight   intensity={0.5}
                                style={{
                                color: 'white',
                                transform: [
                                    {translate: [0, 0, 0]},
                                    {rotateX: 45}]
                                }}/&gt;
            &lt;PointLight intensity={5}
                        style={{
                            color: '#00f',
                            transform: [{translate: [0.1, -1, -2]}]
                        }}/&gt;
            &lt;Box ... /&gt;
            &lt;Cylinder ... /&gt;
            &lt;Sphere ... /&gt;
        &lt;/View&gt;</pre><p></p>

<p><code>intensity</code>プロパティはちょっと強めの<code>5</code>にしました。色は青色、そして位置はちょっと手前でちょっと下から照らす感じにしています。</p>

<p>すると、こんな感じで、青い光がオブジェクトに反射するような雰囲気になりました。ちょっとムーディで怪しげですね。</p>

<div id="attachment_23956" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_PointLight-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23956" srcset="/wp-content/uploads/2017/07/Hello3DObject2_PointLight.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_PointLight-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_PointLight-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">PointLightを反映させた3Dプリミティブオブジェクト</p></div>

<p>さて、これで終了にしてもいいのですが、全体的にちょっと暗いですよね、そこで光の調整をしたいと思います。</p>

<p>では<code>AmbientLight</code>コンポーネントを配置してみましょう。AmbientLightは環境光で、全てのオブジェクトに均等に光を当てるという機能を持っています。<code>AmbientLight</code>コンポーネントを使うことで、全体的な光の加減を微調整することもできます。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
            &lt;Pano ... /&gt;
            {/* Lighting */}
            &lt;DirectionalLight intensity={0.5}
                                style={{
                                color: 'white',
                                transform: [
                                    {translate: [0, 0, 0]},
                                    {rotateX: 45}]
                                }}/&gt;
            &lt;PointLight intensity={5}
                        style={{
                            color: '#00f',
                            transform: [{translate: [0.1, -1, -2]}]
                        }}/&gt;
            &lt;AmbientLight intensity={0.3}/&gt;
            &lt;Box ... /&gt;
            &lt;Cylinder ... /&gt;
            &lt;Sphere ... /&gt;
        &lt;/View&gt;</pre><p></p>

<p><code>intensity</code>プロパティは、ほんの少しだけ設定しました。これでブラウザをリロードしてみると、ほんのりと明るくなったことがわかると思います。</p>

<div id="attachment_23947" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23947" srcset="/wp-content/uploads/2017/07/Hello3DObject2_AmbientLight.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">AmbientLightを反映させた3Dプリミティブオブジェクト</p></div>

<p>いろいろな形状のものを置き、ライティングを終えたところで、こんな風に思った方はいないでしょうか。<br />
「現実世界で立方体や球なんて、積み木とかにしか存在しないじゃないか！」<br />
と。</p>

<p>四角や丸を置くためにVRを始めたわけじゃないんだという気持ちはよくわかりますので、次回は応用編として既存の3DモデルをReact VRで扱う方法について解説していきます。</p>
]]></content:encoded>
		
		<series:name><![CDATA[React VR]]></series:name>
	</item>
		<item>
		<title>React VR×360度画像！Web上でパノラマVR表示を試す</title>
		<link>/karad5/23885/</link>
		<pubDate>Mon, 26 Jun 2017 01:00:06 +0000</pubDate>
		<dc:creator><![CDATA[原一浩]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[GearVR]]></category>
		<category><![CDATA[React VR]]></category>
		<category><![CDATA[WebVR]]></category>

		<guid isPermaLink="false">/?p=23885</guid>
		<description><![CDATA[連載： React VR (2)前回は、React VRのインストールから「Hello, World」の表示、そして日本語の表示までを行いました。 今回は、RICOH THETAなどで撮影した360度画像をVRコンテンツ...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/react-vr/" class="series-453" title="React VR" data-wpel-link="internal">React VR</a> (2)</div><p><a href="https://html5experts.jp/karad5/23543/" target="_blank" data-wpel-link="internal">前回</a>は、React VRのインストールから「Hello, World」の表示、そして日本語の表示までを行いました。
今回は、RICOH THETAなどで撮影した360度画像をVRコンテンツとして表示してみましょう。</p>

<div id="attachment_23871" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/Screenshot_20170620-162554-640x360.png" alt="" width="640" height="360" class="size-large wp-image-23871" srcset="/wp-content/uploads/2017/06/Screenshot_20170620-162554.png 640w, /wp-content/uploads/2017/06/Screenshot_20170620-162554-300x169.png 300w, /wp-content/uploads/2017/06/Screenshot_20170620-162554-207x116.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">今回のサンプルの完成品</p></div>

<h2>React VRプロジェクトのフォルダ構成について</h2>

<p>と、その前にちょっとしたおさらいです。</p>

<p><a href="https://html5experts.jp/karad5/23543/" target="_blank" data-wpel-link="internal">前回</a>は、「ちょっと日本語を表示したい!」というところから、いきなりハードな展開へとなってしまいましたが、ここでちょっと、React VRプロジェクトがどのような構成になっているのかを確認しておきましょう。</p>

<p></p><pre class="crayon-plain-tag">.
├── .babelrc
├── .flowconfig
├── .gitignore
├── .watchmanconfig
├── tests
│   └── client.js
├── index.vr.js
├── node_modules
├── package.json
├── rn-cli.config.js
├── static_assets
│   └── chess-world.jpg
├── vr
│   ├── client.js
│   └── index.html
└── yarn.lock</pre><p></p>

<p>「.」で始まる各種ドットファイル達は、ビルド用だったり、flowやwatchmanといったツールのための設定ファイルです。</p>

<p>いくつかファイルやフォルダがありますが、React VRの開発に必要な部分は、React VRにおけるRootコンポーネント(大元のコンポーネント)となる「index.vr.js」と、実際にブラウザでReact VRコンテンツをマウントするためのファイルとしての「vr/」以下の各種ファイル、そして各種静的リソースのためのアセットディレクトリ「static_assets」が中心となります。ここには、フォントやテクスチャなどを配置します。</p>

<p>React Nativeの開発をした方は「おっ」と思ったかもしれませんが、「index.android.js」「index.ios.js」などと同じような位置づけで「index.vr.js」という命名規則となっているのです。そして、フレームワークの構成的には「今はWeb出力がメインということでreact-vr-webを使っていまっせ」ということが読み取れます。この構成から見て、将来的にはネイティブデバイス向けのビルドも考えていることが期待できそうです。</p>

<h2>jestを使用してReact VRのテストを実行する</h2>

<p>「<strong>tests</strong>」というのは、テスト用のファイルを配置するディレクトリです。Facebook製のテストフレームワーク<code>jest</code>を実行すると、ここにあるファイルが対象となってテストが実行されます。あらかじめプロジェクトにはテストの実行が可能になっています。</p>

<p>テストの実行には<code>jest</code>が必要なので、下記のようにインストールしておきましょう。</p>

<p></p><pre class="crayon-plain-tag">$ npm install -g jest</pre><p></p>

<p>testコマンドで実行ができます。ただし、下記のように失敗します。</p>

<p></p><pre class="crayon-plain-tag">$ npm test

&gt; HelloWorld@0.0.1 test C:\****\HelloWorld
&gt; jest

 FAIL  __tests__\client.js
  ● Test suite failed to run

    Cannot find module 'Mesh' from 'setup.js'

      at Resolver.resolveModule (node_modules\jest-resolve\build\index.js:169:17)
      at Object.&lt;anonymous&gt; (node_modules\react-vr\jest\setup.js:22:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        12.811s
Ran all test suites.
npm ERR! Test failed.  See above for more details.</pre><p></p>

<p>実は、GitHubにはもうissueとして反映されているのですが、react-vrライブラリの不具合なようです。解決策も提示されているので、もうしばらくすると正しく動作するようになると思います。</p>

<ul>
<li><a href="https://github.com/facebook/react-vr/commit/f9c2b537ee5b60ec45d2c6b5fb3aaa72d45f7f3e" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Fixed bug where npm test for init project would not pass &#8211; because je… · facebook/react-vr@f9c2b53</a></li>
</ul>

<p>VRのテスト周りもプロジェクトにセットアップ済というのは、なかなか嬉しいことですね。</p>

<h2>パノラマVRはこんなにも簡単!</h2>

<p>さて、ファイル構成などの意味もわかってきてスッキリしたところで、ちょっと実践的なコンテンツを作成してみましょう。</p>

<p>すぐ作れてインパクトも強く、応用性が高いVRコンテンツといえば、パノラマVRコンテンツでしょう。実際、これまで作ってきた「Hello World!」は、パノラマ背景に背景色付きテキストが宙に浮かぶというものでした。パノラマVRコンテンツというのは、360度写真さえあれば、すぐに作成することが出来るのです。</p>

<p>とはいえ、いざ360度写真を使おうと思っても<a href="https://theta360.com/ja/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">RICOH THETA</a>のユーザでもない限り、360度写真の準備をするのは大変です。そこで僕は友人の寺田さんが撮ってきた360度写真をお借りすることにしました。寺田さんは、<a href="https://www.cmscom.jp/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">株式会社CMSコミュニケーションズ</a>という会社の社長であるのですが、かなり古くからのTHETAユーザで、360度写真を撮り続けておられます。また、Plone Ambassadorや元PyCon JPの座長などを務めたりなど精力的な活動をされています。</p>

<p>さて、今回は寺田さんがニューヨークに行った時の写真をお借りしました。また、写真のライセンスは「<a href="https://creativecommons.org/licenses/by/4.0/deed.ja" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">CC-BY 4.0 国際</a> (<a href="https://twitter.com/terapyon" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">@terapyon</a>)」となりますので、お取り扱いには注意をお願いします。</p>

<div id="attachment_23860" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/2016_10_17__22_05_18-640x320.jpg" alt="" width="640" height="320" class="size-large wp-image-23860" srcset="/wp-content/uploads/2017/06/2016_10_17__22_05_18.jpg 640w, /wp-content/uploads/2017/06/2016_10_17__22_05_18-300x150.jpg 300w, /wp-content/uploads/2017/06/2016_10_17__22_05_18-207x104.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">寺田さんからのニューヨーク写真</p></div>

<h3>新規プロジェクトを作成し、360度写真を配置</h3>

<p>それでは、新しくプロジェクトを作成してみましょう。<code>ReacrVrSamplePano</code>というプロジェクト名にしてみます。</p>

<p></p><pre class="crayon-plain-tag">$ react-vr init ReacrVrSamplePano</pre><p></p>

<p>プロジェクトディレクトリ内へ移動しておきます。</p>

<p></p><pre class="crayon-plain-tag">$ cd ReacrVrSamplePano</pre><p></p>

<p>プロジェクトの作成が終わったら、下記リンク先から写真をダウンロードし、プロジェクトの「static_assets」ディレクトリへ配置しましょう。</p>

<ul>
<li><a href="https://html5experts.jp/wp-content/uploads/2017/06/2016_10_17__22_05_18.zip" data-wpel-link="internal">寺田さんからのニューヨーク360度写真</a></li>
</ul>

<p>配置が終わったら「index.vr.js」を開いて、<code>ReacrVrSamplePano</code>クラスを下記のように編集します。</p>

<p></p><pre class="crayon-plain-tag">export default class ReacrVrSamplePano extends React.Component {
  render() {
    return (
      &lt;View&gt;
        &lt;Pano source={asset('2016_10_17__22_05_18.jpg')}/&gt;
      &lt;/View&gt;
    );
  }
};</pre><p></p>

<p>なんと！<a href="https://html5experts.jp/karad5/23543/" target="_blank" data-wpel-link="internal">前回</a>の 「Hello World!」プロジェクトよりも短くなってしまいました。これは非常に楽勝ですね！などと調子に乗らないようにしましょう。内部では複雑なことが行われているのです。</p>

<p>さて、<code>Pano</code>コンポーネントとは何でしょうか。Panoというのは、<a href="https://facebook.github.io/react-vr/docs/pano.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">React VRのドキュメント</a>によれば、1000mの球だということです。これはユーザーを中心に絶対配置されており、内側に360度画像が投影されています。</p>

<p><code>Pano</code>コンポーネントは、JSX上では1行ですが、実際は内部で複雑なことをしています。<code>Pano</code>コンポーネントのソースはこちらになります。</p>

<ul>
<li><a href="https://github.com/facebook/react-vr/blob/master/ReactVR/js/Views/Pano.js" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">react-vr/Pano.js at master · facebook/react-vr</a></li>
</ul>

<p>えらく長いソースだなあと思われたかもしれませんが、このコンポーネントは、<code>RCTBaseView</code>というクラスを継承しているので、実はもっと長いロジックを持っています。ポイントとしては、Panoは、球体なのでTHREE.SphereというThree.jsの球オブジェクトを内部で持っているという点です。</p>

<p>ここで言いたいことは、上記のソースをすべて読んで理解しましょうということではありません。大事なことはフレームワークの表面的な使い方だけでなく、いざとなったら元ソースも覗いてやろうという気概なのです。</p>

<p>そうそう、コードを変更したところで話が止まっていました。さっそくブラウザで見るためにプロジェクトを実行しましょう。</p>

<p></p><pre class="crayon-plain-tag">$ npm start</pre><p></p>

<p><code>HelloWorld</code>プロジェクトのときと同じようにブラウザで表示してみましょう。無事ニューヨークの景色がブラウザで表示されていれば完成です。</p>

<h2>GearVRで見てみる</h2>

<p>もし、GearVRとGalaxy系のスマートフォンを持っていたら」という前提があるのですが、持っていたら是非ここで紹介するGearVRによるパノラマVRコンテンツを体験してみてください。</p>

<p>PCのブラウザやスマートフォンで表示させたものも結構感動しますが、GearVRでこれを表示してみると感動は何倍にもなります。GearVRを使うと、センサーのおかげで顔のトラッキングがスムーズですし、CarmelというVRブラウザを使えばWeb上のVRコンテンツもすぐに体験できます。Carmelは、GearVR内のアプリストアにてダウンロードすることができます。</p>

<div id="attachment_23863" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/Carmel-Developer-Preview-Oculus-640x412.png" alt="" width="640" height="412" class="size-large wp-image-23863" srcset="/wp-content/uploads/2017/06/Carmel-Developer-Preview-Oculus.png 640w, /wp-content/uploads/2017/06/Carmel-Developer-Preview-Oculus-300x193.png 300w, /wp-content/uploads/2017/06/Carmel-Developer-Preview-Oculus-207x133.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">Carmelのサイトキャプチャ</p></div>

<p>ただし、デベロッパープレビュー中のCarmelでVRコンテンツを見るためには、ちょっとした前準備が必要になります。Oculusのサイトの<a href="https://developer.oculus.com/documentation/vrweb/latest/concepts/carmel-launching-content/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Launching Your Content</a>を見つつ進めていきましょう。</p>

<p>まず、<code>vr/</code>以下に<code>ovr.html</code>というファイル名で下記を作成します。</p>

<p></p><pre class="crayon-plain-tag">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;title&gt;ovr&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;a href="ovrweb:http://あなたのPCのIPアドレス:8081/vr"&gt;
  Navigate to an HTTP experience
&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;</pre><p></p>

<p>ちなみに、「<strong>あなたのPCのIPアドレス</strong>」は各自のPCのIPアドレスとなります。
ここで書かれているのは、aタグによりVRコンテンツへのリンクが表示されるだけのHTMLですが、リンク先の<code>http</code>の前に<code>ovrweb</code>というプロトコルがついています。
このプロトコルをCarmelがインストールされたスマートフォンで開くと、Carmelが立ち上がり、GearVRへのセットを促されます。
それでは、「http://あなたのPCのIPアドレス:8081/vr/ovr.html」をスマートフォンで開いて、リンクをクリックしてみましょう。</p>

<div id="attachment_23868" style="width: 370px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/Screenshot_20170620-144349-360x640.png" alt="" width="360" height="640" class="size-large wp-image-23868" srcset="/wp-content/uploads/2017/06/Screenshot_20170620-144349.png 360w, /wp-content/uploads/2017/06/Screenshot_20170620-144349-169x300.png 169w, /wp-content/uploads/2017/06/Screenshot_20170620-144349-116x207.png 116w" sizes="(max-width: 360px) 100vw, 360px" /><p class="wp-caption-text">GearVRに促すガイドが表示される</p></div>

<p>リンクをタップした後のガイダンスに従いスマートフォンをGearVRに装着し、頭にGearVRを装着すると、目の前にはニューヨークが広がるはずです(後ろを振り向くと寺田さんに会えることでしょう)。</p>

<div id="attachment_23871" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/Screenshot_20170620-162554-640x360.png" alt="" width="640" height="360" class="size-large wp-image-23871" srcset="/wp-content/uploads/2017/06/Screenshot_20170620-162554.png 640w, /wp-content/uploads/2017/06/Screenshot_20170620-162554-300x169.png 300w, /wp-content/uploads/2017/06/Screenshot_20170620-162554-207x116.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">今回のサンプルの完成品</p></div>

<p>ただ日本語については、Carmel上だとPCブラウザで見た時ほど綺麗に表示されないことがわかります。Carmelがデベロッパープレビュー版だから起きるのか、レンダリングエンジンのせいかは不明ですが、今後改善されることを期待しましょう。</p>

<div id="attachment_23874" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/Screenshot_20170620-162915-640x360.png" alt="" width="640" height="360" class="size-large wp-image-23874" srcset="/wp-content/uploads/2017/06/Screenshot_20170620-162915.png 640w, /wp-content/uploads/2017/06/Screenshot_20170620-162915-300x169.png 300w, /wp-content/uploads/2017/06/Screenshot_20170620-162915-207x116.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">GearVRで見ると、日本語表示がすこしおかしい</p></div>

<h2>まとめ</h2>

<p>WebVRは、その技術構成上、どうしてもネイティブなVRコンテンツよりも制約事項が多くなります。</p>

<p>一方で、「Webページを表示するだけでVRコンテンツを見ることができる」「ヘッドマウントディスプレイがなくてもある程度の体験が味わえる」という手軽さは、非常に魅力的です。</p>

<p>近しい人が撮った360度写真や動画などは、今までの付き合いなどといった経験が加味されて、よりリアルにコンテンツを味わうことが可能になる可能性を秘めています。表現としてのリアルよりも、自分と関係があるコンテンツという意味でのリアルさ、これはひょっとしたらネイティブVRにない強みになるかもしれません。</p>

<p>次回は、React VRにおける3Dプリミティブの利用や、3Dモデルの配置などを見ていきましょう。</p>

<p>※ 今回のサンプルプロジェクト2つは、GitHubに置いてあります。利用方法、ライセンスなどをお守りの上、ご利用ください。</p>

<ul>
<li><a href="https://github.com/karad/html5_react_vr_samples" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">karad/html5_react_vr_samples</a></li>
</ul>
]]></content:encoded>
		
		<series:name><![CDATA[React VR]]></series:name>
	</item>
		<item>
		<title>React VRで始めるお手軽WebVRプログラミング</title>
		<link>/karad5/23543/</link>
		<pubDate>Fri, 23 Jun 2017 01:00:54 +0000</pubDate>
		<dc:creator><![CDATA[原一浩]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[React VR]]></category>
		<category><![CDATA[WebVR]]></category>

		<guid isPermaLink="false">/?p=23543</guid>
		<description><![CDATA[連載： React VR (1)React VRというのは、Facebookが開発し、GitHubにてBSDライセンスで公開しているオープンソースのVRアプリケーションフレームワークです。現在のところは、Webブラウザ向...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/react-vr/" class="series-453" title="React VR" data-wpel-link="internal">React VR</a> (1)</div><p><a href="https://facebook.github.io/react-vr/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">React VR</a>というのは、Facebookが開発し、GitHubにてBSDライセンスで公開しているオープンソースのVRアプリケーションフレームワークです。現在のところは、Webブラウザ向けにWebGLとWebVRを使ったVRアプリケーションを作るための様々な仕組みを提供しています。</p>

<div id="attachment_23874" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/Screenshot_20170620-162915-640x360.png" alt="" width="640" height="360" class="size-large wp-image-23874" srcset="/wp-content/uploads/2017/06/Screenshot_20170620-162915.png 640w, /wp-content/uploads/2017/06/Screenshot_20170620-162915-300x169.png 300w, /wp-content/uploads/2017/06/Screenshot_20170620-162915-207x116.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">VRコンテンツは、実行して動いた時の満足感がかなり高いです</p></div>

<p>React VRを知らなくても、ReactやReact Nativeなら知っているという人もいるかもしれません。VRコンテンツを作るには新しいフレームワークやライブラリなどを学ぶ必要がありましたが、Reactと同じ考え方を使ってVRコンテンツを作ることができる点が、他のフレームワークと異なる点です。</p>

<h2>ネイティブVRが最高の体験をもたらすとは限らない</h2>

<p>VRというと何らかのVRヘッドマウントを装着して体験するものというイメージがあります。また、VRヘッドマウントは高額で、VRを体験するハードルが高かったことも事実です。そんな中、ある程度のクオリティを保ちつつも安価なVRヘッドマウントとして登場したのが、GearVRです。</p>

<p>私もGearVRはすぐに購入してゲームや体験系コンテンツをいろいろと試してみました。もちろん、ジュラシックワールドの恐竜にはリアリティを感じましたし、3Dのシューティングゲームでは3D酔いも体験しました。
しかし、個人的に一番衝撃を受けたのは<a href="http://www.vr-cruise.com/index.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">VR CRUISE</a>の産経フォトです。</p>

<div id="attachment_23847" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/Screenshot_2016-03-15-00-03-21-640x360.png" alt="" width="640" height="360" class="size-large wp-image-23847" srcset="/wp-content/uploads/2017/06/Screenshot_2016-03-15-00-03-21.png 640w, /wp-content/uploads/2017/06/Screenshot_2016-03-15-00-03-21-300x169.png 300w, /wp-content/uploads/2017/06/Screenshot_2016-03-15-00-03-21-207x116.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">当時の産経フォト</p></div>

<p>特に、「東日本大震災でのタンカーが乗り上げている風景のパノラマ写真」には一番度肝を抜かれました。作りとしては360度写真であり、すごいポリゴン技術を利用しているわけではないのですが、コンテンツが日常生活と地続きにあるという感覚が、リアリティを感じさせ、恐怖を感じさせたのです。</p>

<p>そこで思ったことは、VRといっても受け手の中にある感性によっては、シンプルなコンテンツでも十分に伝わる体験があるということでした。</p>

<h2>React VRのアーキテクチャをざっと知る</h2>

<div id="attachment_23880" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/React-VR-A-framework-for-building-VR-apps-using-React-640x412.png" alt="" width="640" height="412" class="size-large wp-image-23880" srcset="/wp-content/uploads/2017/06/React-VR-A-framework-for-building-VR-apps-using-React.png 640w, /wp-content/uploads/2017/06/React-VR-A-framework-for-building-VR-apps-using-React-300x193.png 300w, /wp-content/uploads/2017/06/React-VR-A-framework-for-building-VR-apps-using-React-207x133.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">React VRの公式サイト</p></div>

<p>React VRを語る上で欠かせないのが、WebVRという仕様と、Three.jsというライブラリの存在です。<a href="https://webvr.info/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">WebVR</a>は、VRヘッドマウント事態の情報やリアルタイムな傾きや向きなどをWebブラウザへと伝えるための仕様で、これによりGearVRなどでWebVRを閲覧することが出来ます。
Three.jsは、3Dのライブラリです。本誌でも過去に特集されているので改めての説明は省きます。</p>

<p>React VRは、WebVRとThree.jsをJavaScriptでごりごりと作っていくという世界観にもう2レイヤー加えたようなものと言えます。WebVRとThree.jsは、OVRUIというレイヤーでラッピングされ、そのAPIをReactコンポーネントを通じてユーザーは利用するということになります。</p>

<h2>早速作ってみよう</h2>

<p>では早速、React VRでまずはプログラムを作ってみましょう。React VRに付属している「Hello World」サンプルで、一通りの最低限な使い方を学んでみることにします。</p>

<p>React VRはReactとついているので、ちょっと怖気づいてしまうかもしれませんが、サンプル自体は非常に簡単です。まず初めに言っておきますと、React VRではターミナル(コマンドプロンプト)を頻繁に使います。なので、MacOSであれば「ターミナル」、Windowsであれば「コマンド プロンプト」を使ってサンプル作成を進めることになります（以降はWindows環境を前提として進めますが、Macでも同様に試して頂けます）。</p>

<h2>React VRのコンソールツールをインストール</h2>

<p>React VRには、<code>react-vr-cli</code>というコンソールツールが用意されており、インストールすると<code>react-vr</code>というコマンドが使えるようになります。ということで、なにはともあれこのツールをインストールしましょう。<code>react-vr-cli</code>は、Node.js製のツールなのでまだな方は「<a href="https://nodejs.org/ja/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Node.js</a>」を導入しておきましょう。</p>

<p>続いて<code>react-vr-cli</code>を、Node.jsのパッケージマネージャーであるnpmコマンドでインストールしていきます。</p>

<p></p><pre class="crayon-plain-tag">$ npm install -g react-vr-cli

... 略 ...

C:\Program Files (x86)\Nodist\bin\react-vr -&gt; C:\Program Files (x86)\Nodist\bin\node_modules\react-vr-cli\index.js
C:\Program Files (x86)\Nodist\bin
`-- react-vr-cli@0.3.2</pre><p></p>

<p>最後のメッセージから、<code>react-vr-cli</code>のバージョン0.3.2がインストールされたことが確認できます。</p>

<p>まず試しに<code>react-vr</code>コマンドを実行してみましょう。</p>

<p></p><pre class="crayon-plain-tag">$ react-vr

React VR Command Line Interface
Version 0.3.2

Usage:
  react-vr init [project name]  Create a new React VR application with the specified name</pre><p></p>

<p>コマンドの出力結果から、<code>react-vr</code> コマンドには <code>init</code> というサブコマンドが一つだけ用意されていることがわかります。コマンドにプロジェクト名を渡すと、新規React VRプロジェクトが作成されるようです。今回は「Hello World」を表示させるので、<code>HelloWorld</code>というプロジェクト名にします。</p>

<p></p><pre class="crayon-plain-tag">$ react-vr init HelloWorld</pre><p></p>

<p>Enterキーを押すとなにやらいろいろとプログラムが走り出して、ごにょごにょと長いメッセージが表示されたあと、プロンプトへ戻ります。これで、<code>HelloWorld</code>プロジェクトが作成されました。</p>

<p>続いて、「HelloWorld」ディレクトリに入り、早速何も変更しないまま実行してみましょう。<code>npm start</code>というコマンドを使います。</p>

<p></p><pre class="crayon-plain-tag">$ cd HelloWorld
$ npm start</pre><p></p>

<p>すると、またごちゃっとメッセージがコマンドラインに表示されて、<code>Loading dependency graph, done.</code>というメッセージが最後に表示されます。</p>

<p></p><pre class="crayon-plain-tag">$ npm start

&gt; HelloWorld@0.0.1 start C:\****\HelloWorld
&gt; node -e "console.log('open browser at http://localhost:8081/vr/\n\n');" &amp;&amp; node node_modules/react-native/local-cli/cli.js start

open browser at http://localhost:8081/vr/

... 略 ...

Loading dependency graph, done.</pre><p></p>

<p>この表示が出たら、ブラウザで<code>http://localhost:8081/vr/</code>を開いてみましょう。</p>

<div id="attachment_23853" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/HelloWorld-640x406.png" alt="" width="640" height="406" class="size-large wp-image-23853" srcset="/wp-content/uploads/2017/06/HelloWorld.png 640w, /wp-content/uploads/2017/06/HelloWorld-300x190.png 300w, /wp-content/uploads/2017/06/HelloWorld-207x131.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">helloと表示された。一安心。</p></div>

<p>「hello」と表示されているのがわかると思います。マウスで画面をドラッグしてみましょう。</p>

<h2>ちゃんとHello World!にする</h2>

<p>さて、「hello」と表示されているのは確認できましたので、今度はプログラムを修正して、ちゃんと「Hello World!」と出力されるようにしてみましょう。プロジェクトフォルダ内にある「index.vr.js」を開いてください。</p>

<p>エディタは各自使い慣れたもので構いません。ただしReact VRの新規プロジェクト作成で行った場合、<strong>ECMAScript 2015(ES6)形式でコードが生成されます</strong> 。また、JSX (React専用の特殊な記法) も使用するので、これらのスタイルに対応しているエディタを使用しましょう。<a href="https://code.visualstudio.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Visual Studio Code</a>であれば、標準でJSXに対応しているのでおすすめです。</p>

<p>エディタで「index.vr.js」を開くと、こんな箇所があるはずです。ここで、先ほど表示していた3D空間の全要素を定義しています。</p>

<p></p><pre class="crayon-plain-tag">export default class HelloWorld extends React.Component {
  render() {
    return (
      &lt;View&gt;
        &lt;Pano source={asset('chess-world.jpg')}/&gt;
        &lt;Text
          style={{
            backgroundColor: '#777879',
            fontSize: 0.8,
            fontWeight: '400',
            layoutOrigin: [0.5, 0.5],
            paddingLeft: 0.2,
            paddingRight: 0.2,
            textAlign: 'center',
            textAlignVertical: 'center',
            transform: [{translate: [0, 0, -3]}],
          }}&gt;
          hello
        &lt;/Text&gt;
      &lt;/View&gt;
    );
  }
};</pre><p></p>

<p>ここでは通常のReactコンポーネントと同様、<code>React.Component</code>を継承したクラスを定義し、<code>render</code>メソッドをオーバーライドしています。React VRは、通常のReactとほぼ同じスタイルでVRコンテンツを表示できるということです。</p>

<p>ポイントは、<code>render()</code>メソッド内で使用しているコンポーネントです。ここで使用されている<code>View</code>コンポーネントや<code>Pano</code>コンポーネント、<code>Text</code>コンポーネントなどは、React VRの独自コンポーネントなので、使い方を把握する必要があります。</p>

<p><code>View</code>コンポーネントというのは、HTMLでいうところの<code>div</code>だと思ってください。何かのまとまりとして、様々な3D要素を内包出来ますし、<code>View</code>コンポーネント自体にスタイルを適用することもできます。このスタイルは、Reactを使ったことがある方であれば馴染みのある定義方法だということがわかるでしょう。プロパティはCSSと違い、キャメルケースで記述していきます。<strong>ほとんどスタイルシートのような感覚で、3Dオブジェクトのスタイルを定義することができる</strong> のは感動ものです。</p>

<p><code>Pano</code>コンポーネントは、パノラマ写真を埋め込んだ空間を簡単に作成できるコンポーネントです。次回の記事では実際に<code>Pano</code>コンポーネントを使ってVRコンテンツを作ります。</p>

<p>「hello」という文字列が表示されるように定義してあるのは<code>Text</code>コンポーネントです。<code>Text</code>コンポーネントは、文字通りテキストを表示するためのコンポーネントで、スタイルの定義と内容が記述されています。スタイルは見たことがない<code>layoutOrigin</code>というプロパティなどはありますが、他はほぼCSSのままであることが確認できると思います。</p>

<p>では、「hello」を「Hello World!」へ書き換えていきましょう。書き換えた<code>Text</code>コンポーネント部分はこんな感じになります。</p>

<p></p><pre class="crayon-plain-tag">&lt;Text
  style={{
    backgroundColor: '#777879',
    fontSize: 0.8,
    fontWeight: '400',
    layoutOrigin: [0.5, 0.5],
    paddingLeft: 0.2,
    paddingRight: 0.2,
    textAlign: 'center',
    textAlignVertical: 'center',
    transform: [{translate: [0, 0, -3]}],
  }}&gt;
  Hello World!
&lt;/Text&gt;</pre><p></p>

<p>さて、ブラウザをリロードしてみましょう。無事「Hello World!」と表示されたことと思います。</p>

<div id="attachment_23855" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/HelloWorld-2-640x406.png" alt="" width="640" height="406" class="size-large wp-image-23855" srcset="/wp-content/uploads/2017/06/HelloWorld-2.png 640w, /wp-content/uploads/2017/06/HelloWorld-2-300x190.png 300w, /wp-content/uploads/2017/06/HelloWorld-2-207x131.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">Hello World!と表示された</p></div>

<h2>日本語を表示させたら、***になった!</h2>

<p>ただ、実はReact VRは現在のバージョンでは、そのままでは日本語の表示ができません。試しに「Hello, World!」の代わりに日本語を入れて試してみると、以下のように文字列が「***」と表示されてしまいます。</p>

<div id="attachment_23856" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/HelloWorld-jp-640x406.png" alt="" width="640" height="406" class="size-large wp-image-23856" srcset="/wp-content/uploads/2017/06/HelloWorld-jp.png 640w, /wp-content/uploads/2017/06/HelloWorld-jp-300x190.png 300w, /wp-content/uploads/2017/06/HelloWorld-jp-207x131.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">日本語を表示しようとしたら***になるの巻</p></div>

<p>詳しくはReact VRのドキュメント「<a href="https://facebook.github.io/react-vr/docs/fonts.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Fonts and Text</a>」に書かれていますが、大きく分けて2つのステップで日本語表示が実現できます。</p>

<h3>1. まずは日本語フォントをダウンロード</h3>

<p>React VRのGitHubへ行き、<code>OVRUI/fonts</code>以下にある「japanese.fnt」「japanese.png」をダウンロードします。</p>

<ul>
<li><a href="https://github.com/facebook/react-vr/tree/master/OVRUI/fonts" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">react-vr/OVRUI/fonts at master · facebook/react-vr</a></li>
</ul>

<p>ダウンロードしたフォント定義ファイルおよびフォントセットテクスチャは、「static_assets/fonts」以下に配置します。「fonts」ディレクトリは自身で作成してください。
ちなみに、「japanese.fnt」「japanese.png」は、独自のものを作ることもできますし、React VRに用意されているこちらの「<a href="https://github.com/facebook/react-vr/tree/master/tools/fontue" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">react-vr/tools/fontue at master · facebook/react-vr</a>」ツールを使って作ることも出来ます。オリジナルのフォントセットテクスチャを作成する場合はフォントのライセンスをご確認の上利用しましょう。</p>

<h3>2. 日本語フォントを読み込むように「vr/client.js」を修正</h3>

<p>日本語フォントを使うようにするには、「vr/client.js」を修正します。8行目以下に下記のような行があることと思います。</p>

<p></p><pre class="crayon-plain-tag">function init(bundle, parent, options) {
  const vr = new VRInstance(bundle, 'HelloWorld', parent, {
    // Add custom options here
    ...options,
  });
  vr.render = function() {
    // Any custom behavior you want to perform on each frame goes here
  };
  // Begin the animation loop
  vr.start();
  return vr;
}</pre><p></p>

<p>ここを修正していきます。ポイントは下記3点です。</p>

<ol>
<li>OVRUIライブラリをインポートする</li>
<li><code>OVRUI.loadFont</code>メソッドで読み込むフォントセットと読み込み後の処理を記述する</li>
<li>React VR Webの新しいインスタンスを作成するときのオプションに読み込んだフォントを指定する</li>
</ol>

<p>OVRUIというのは、WebVRのためのフレームワークで、Three.jsのシーン(様々な3Dオブジェクトを置く場所)をラップしてVRヘッドマウントを含むデバイスからアクセスできるようにしたり、3Dのビューをテキストつきでレンダリングしたりといった機能を含んでいます。</p>

<p>このうち、テキストのレンダリングについては、Signed-Distance Functionという仕組みを使ってなめらかなフォントレンダリングを行う仕組みが用意されています。この仕組みのおかげで、フォントを導入するのが面倒な感じになっているのですが、フォントのレンダリング面では、3Dに表示するものとしてはゆがみが少なく、読みやすいものになっているのではと思います。</p>

<p>ということでやるべきこととしては、この仕組みに対応したフォント関係のファイルを用意し、VRコンテンツの開始前にフォント定義ファイルおよびフォントセットテクスチャを読み込み、その後コンテンツが始まるように書くことで、日本語に対応した表示を実現することができるのです。</p>

<p><code>OVRUI.loadFont</code>メソッドの返り値は、<code>Promise</code>です。なので、<code>then</code>メソッドを使うことで、読み込み後の処理の中で<code>vr</code>インスタンスを返す処理を書けばいいということになります。<code>Promise</code>については、過去の高津戸さんの記事「<a href="https://html5experts.jp/takazudo/17107/" data-wpel-link="internal">Promiseで簡単！JavaScript非同期処理入門【前編】</a>」が詳しいです。</p>

<p>また、<code>OVRUI.loadFont</code>メソッドの実行結果は、<code>font</code>という値で取得するように書いているので、これを初期化オプションに<code>font</code>というキーに含めて渡してあげます。</p>

<p>以上の処理を書き加えたものが以下となります。</p>

<p></p><pre class="crayon-plain-tag">import * as OVRUI from 'ovrui'; // ← 追加

function init(bundle, parent, options) {
  OVRUI.loadFont(
          '/static_assets/fonts/japanese.fnt',
          '/static_assets/fonts/japanese.png'
  ).then((font) =&gt; {
    const vr = new VRInstance(bundle, 'HelloWorld', parent, {
      // Pass in the custom font as an initialization property
      font: font, // ← 追加
      ...options,
    });
    vr.render = function() {
      // Any custom behavior you want to perform on each frame goes here
    };
    // Begin the animation loop
    vr.start();
    return vr;
  });
}</pre><p></p>

<p>意外に大変でしたが、これで日本語の表示ができるようになったはずです。「Hello World!」のところを日本語にし、コンソールで一旦コンソールを再起動したあと、ブラウザをリロードしてみてください。</p>

<div id="attachment_23858" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/06/HelloWorld-jp-2-640x406.png" alt="" width="640" height="406" class="size-large wp-image-23858" srcset="/wp-content/uploads/2017/06/HelloWorld-jp-2.png 640w, /wp-content/uploads/2017/06/HelloWorld-jp-2-300x190.png 300w, /wp-content/uploads/2017/06/HelloWorld-jp-2-207x131.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">無事日本語を表示できるようになった</p></div>

<p>今回は「Hello, World」と日本語コンテンツの表示を行いました。次回はいよいよ、360度画像を用いたパノラマ表示にチャレンジしていきます。</p>
]]></content:encoded>
		
		<series:name><![CDATA[React VR]]></series:name>
	</item>
	</channel>
</rss>
