2015年4月15日
前回の更新からずいぶん時間が経ってしまいましたが、拡大縮小ソリューションの第2弾のご紹介です。
第2弾はマイクロソフトの提供する「DeepZoom」です。DeepZoom自体は2008年頃に公開された技術で、Silverlight2の機能として実装されました。名称からもわかるようにSilverlightはAdobeのFlashを意識したRIAアプリケーション開発用のフレームワークです。マイクロソフト製ということでVisualStudioとの親和性が非常に高く、おなじみの.NET系言語で開発できるところも大きな強みでした。ところが、その後の時代の流れはSilverlightでもFlashでもなく、汎用的なHtml5へとシフトしていったのは皆さんも御存知のとおりです。
DeepZoomについては、Silverlightから独立してHtml5版がマイクロソフト自身からリリースされています。Html5版は名称が変わりSeadragonAjax※1といいます。現在ではマイクロソフトの公式版はプロジェクトが終了していますが、その後継としてオープンソース版のOpenSeadragonが開発されています※2。
さて、DeepZoomの原理としては前述のGoogleMapsと同じく、ズーム率に応じてタイリングされた画像を動的に読み込む仕掛けです。ただ、元がSiverlightというリッチアプリケーションに由来するので動作は非常にスムーズで、GoogleMapsよりも操作感は滑らかです。またGoogleMapsが地図表示APIという前提があるのに対して、DeepZoomは画像表示のための汎用的な作りになっているので、扱いもシンプルです。以下が作成したサンプルになります(OpenSeadragonでの実装)。
DeepZoomで画像を読み込むには、元画像をタイルに分割する必要がありますが、分割についてはマイクロソフトから公式ツールが出ています。「Deep Zoom Composer」というこのソフトを使うと極めて簡単にタイリングができます。また、複数の画像を並べてひとつのイメージにすることもできますし、分割したイメージをSilverLightアプリケーションとして出力することもできます。
OpenSeadragonはJavaScriptライブラリで仕様が公開されているため、カスタマイズもしやすくなっています。弊社の担当したプロジェクトでは、このライブラリを使用して巨大な図面ファイルを表示し、その図面上に作画できるHtml5アプリケーションを開発しました※3。作画部分にSVGを使用することで、PhotoshopやIllustratorのようなアプリケーションをブラウザ上で実現することができます。
※1 元々DeepZoomはSeadragon Software社が開発した技術だからです。
※2 OpenSeadragonはGitHubに登録されていて、JavaScript用のパッケージマネージャのbowerからインストールすることもできます。
※3 顧客案件のため画面をお見せすることができませんが、このような技術にご興味のある方は弊社までお問い合わせください。
2014年6月9日
パノラマビューワーの特徴の一つに、自在に拡大縮小できるという点があげられます。制作の過程として複数枚の画像を合成するという手順があるため、画像の解像度が高すぎて画面内に表示しきれないという理由もありますが、元来文化的にもパノラマは拡大・縮小と縁が深い装置でした。様々な観光名所のパノラマポイントに登ると、大抵の場所には望遠鏡が置かれています。望遠鏡を除けば、普通の目線では見えない細部が手に取るように近くに現れ、視界を望遠鏡から外すと世界が豆粒のように小さく見えます。こうしたマクロな視点とミクロな視点を縦横無尽に移動できることが、パノラマの快楽の一つであると言えます。
今、我々にとって最も身近な拡大縮小ソリューションは、何と言ってもGoogle Mapsです。地球規模の視点からご近所の視点まで、縦横無尽に移動することができるという操作感覚は、我々の地図体験に革命をもたらしました。※1
Google Mapsを使ってみると、このエンジンを使用してオリジナルの画像を表示することはできないのかと思いつくこともあるでしょう。実は、GoogleMaps APIにはカスタムマップという機能があり、ユーザがオリジナルの地図を表示することができます。
GoogleMapsの原理はタイリングです。高解像度の画像をすべて読み込むのではなく、必要な部分だけを読み込むことで高速なレスポンスを実現しています。タイリングという技術は極めてポピュラーな手法で、KRPanoでもタイリングを導入することで、高速なロードが出来るようになっています。また皆さんもよくご存知のJPEGも、実はタイリングで画像を圧縮しています。(JPEGではブロックと呼んでいます)
タイリングで画像を読み込むためには、事前に画像をタイルに分割しておく必要があります。またズームに応じて精細度を変えておくとより効率的になります。タイル化自体はPhotoshopなどを使用して手作りすることもできますが、高解像度の画像になるととても手作業では追いつきません。GoogleMaps用のタイルファイルについては、GMapImageCutterというツールが無料で公開されていますので、これを使用するのが現実的です。
GMapImageCutterには簡易的なHtmlを生成する機能も備わっているので、アップロードすればそのままWebページにカスタムマップを表示することができます。
GoogleMapと同じ操作感覚でパノラマを表示することが出来ました。GoogleMapsAPIがそのまま使用できますので、この画像の上にマーカーを載せたり、線分を描いたりと様々な応用が考えられます。過去の事例では、社内のフロアマップを表示し、社員の在籍状態を表示するというソリューションを手がけたことがあります。
次回は、IT業界の巨人がプロデュースした、もうひとつの拡大縮小ソリューションを紹介します。
※1余談ですが、そのはるか以前、ライターの荻窪圭氏がQuickTimeVRで高解像度古地図を表示していました
2014年5月17日
KRPanoスクリプトを使ったゲーム制作。前回はパドルが動くところまで作成しましたが、今回は一気にゲームを仕上げます。まずは完成品をご覧ください。
自分で作っておきながら、結構難しい。3000点あたりから厳しい。
ボールと得点表示、スタートとコンティニューが追加されて、ひと通りゲームとしての形が出来上がりました。ソースコードが長くなってしまったので全てを掲載することはできませんが、全部で270行程度のコードに過ぎません(実ステップはもっと少ない)。
工夫のポイントとしては、「1:壁面に当たるたびにスピードが早くなる」、「2:ボールをパドルで受ける角度によって跳ね返り角度が変化する」といったところです。どちらかというとKRPano特有の工夫というよりも、スカッシュゲーム一般の話題かもしれませんが。
ボールのスピードについては、以下の定義のようにボールのレイヤーに追加のプロパティを持たせています。
<!-- ボール --> <layer name="ball" url="ball.png" width="30" height="30" align="topleft" edge="topleft" zorder="55" enabled="false" visible="true" vector_x="1" vector_y="1" speed="1.0" x="0" y="0" />
この中のvector_x,vector_y,speedというプロパティはKRPano標準のものではなく、今回のプログラムで独自に追加したものです。vector_x,vector_yでボールの進行方向のベクトルを保持し、speedに単位時間あたりの移動量をセットします。前回のプログラムでメインループ処理をasyncloopで実装しましたので、単位時間というのは1/60秒になります(理論的には)。壁面に当たるたびに、このspeed値を増やすことで、だんだんとボールが早くなる動きを実現しています。
2の跳ね返り角度については、少しロジックが複雑です。世間のブロック崩しでは大体2パターンに実装がわかれます。よくあるのが、どんな角度であたってもボールの跳ね返りは常に一定であるタイプ。そして、もうひとつはパドルの端で受けるほど跳ね返り角度が急になるタイプです。往年の名作アルカノイドなどは2番めのパターンで実装されているようです。
今回のプログラムでは第3のパターンとして、より自然なロジックを実装します。ボールの動きに対して、パドルが同じ方向に動きつつ衝突した場合は角度がより急になり、ボールと反対の向きにパドルが動いていると角度が穏やかになるというアルゴリズムです。パドルの動きによってボールに回転を加えるようなイメージですね。
まずはパドルの動きを記憶する仕組みです。
<!-- パドル移動 --> <action name="relocatePaddle"> sub( paddleX, mouse.stagex, 40 ); sub( layer[paddle].movement, paddleX, layer[paddle].x ); copy( layer[paddle].x, paddleX ); </action>
パドル移動時のハンドラで、前回座標との差分を取得します。このゲームではパドルはマウスに追従するため、特に慣性がかからないので、移動は瞬間の差分だけで捉えています。次に衝突時の判定処理です。
<!-- パドルが右方向へ移動中 --> if( layer[paddle].movement GT 0, if( layer[ball].vector_x GT 0, <!-- ボールが右方向へ移動中ならば、右方向へ加速する --> div( movement_rate, layer[paddle].movement, 40 ); if( movement_rate GT 1.0, set( movement_rate, 1.0 ) ); add( layer[ball].vector_x,movement_rate, 1.0 ); , <!-- ボールが左方向へ移動中ならば、右方向へ減速する --> div( movement_rate, layer[paddle].movement, 40 ); if( movement_rate GT 1.0, set( movement_rate, 1.0 ) ); sub( layer[ball].vector_x, 1.0, movement_rate ); decelerateBall(); ); ); <!-- パドルが左方向へ移動中 --> if( layer[paddle].movement LT 0 if( layer[ball].vector_x LT 0, <!-- ボールが左方向へ移動中ならば、左方向へ加速する --> div( movement_rate, layer[paddle].movement, 40 ); if( movement_rate LT -1.0, set( movement_rate, -1.0 ) ); add( layer[ball].vector_x,movement_rate, -1.0 ); , <!-- ボールが右方向へ移動中ならば、右方向へ減速する --> div( movement_rate, layer[paddle].movement, 40 ); if( movement_rate LT -1.0, set( movement_rate, -1.0 ) ); sub( layer[ball].vector_x, -1.0, movement_rate ); decelerateBall(); ); );
KRPanoの条件分岐文にはクセがあるため、少々読みにくいのですが、上記のコードではボールとパドルの動く方法の組み合わせによってvector_xの値を設定しています。向きが揃えば大きい値になり、逆向きならば小さい値になるイメージですね。また減速効果を高めるために、逆向き時にはdecelerateBall()という関数を呼んでいます。この関数の中身はspeed値を下げる実装になっています。
KRPanoスクリプトでは、工夫次第でパノラマとは全く関係のないゲームを作ることまで出来てしまいます。QuickTimeVRが誕生して十数年が経過していますが、パノラマVRコンテンツの表現手法はホットスポットや写真のポップアップ表示、バーチャルツアーといったコンテンツが殆どで、画期的な表現というのはあまり目にすることがありません。言語としてのKRPanoは、今回示したように極めて柔軟な表現力を持っていますので、弊社でもパノラマVRコンテンツにどんどん新しい表現を取り込んでいきたいと考えております。
2014年5月5日
KRPanoスクリプトのトリックを幾つかご紹介してきましたが、今回はもうひねりしてKRPanoスクリプトを使用したゲームを作っていきたいと思います。KRPanoを使ったゲームとしてよくあるのが、パノラマ内に小さなホットスポットを埋め込んでそれをクリックすると当たり、というような宝探しゲームです。仕掛けとしてはホットスポットを埋め込むだけなので造作も無いことですが、360度を自由に拡大縮小できる宝探しというのはパノラマVRならではのゲームと言えます。
しかし、今回はあえてパノラマを使わないゲームを制作したいと思います。KRPanoはパノラマVRのためのスクリプト言語ですが、汎用的なプログラミング言語としての機能も備えているのです。今回製作するのは「スカッシュゲーム」です。8ビットマイコン少年だったプログラマならば、誰でも一度は作ったことがある王道テーマです。簡単に説明しますと、スカッシュゲームは画面下部に左右に動くだけのパドルがあり、上から飛んでくるボールを跳ね返すゲームです。ボールは壁や天井にあたって再び戻ってきて、それをゲームオーバになるまで繰り返します。このゲームを進化させたものがテニスゲームやブロック崩しになるわけです。
ゲーム制作はなかなか面倒なので、まずはパドルをマウスで左右に動かすところまで作ってみます。先回りになりますが出来上がったものをご覧ください。
背景が宇宙なのは往年のブロック崩しのイメージ
ご覧のとおり、通常のゲームっぽいものが動いています(しかも素晴らしいことにFlash/Html5ハイブリッド仕様)。全くパノラマとは関係ありませんが、これはすべてKRPanoスクリプトだけで記述しています。コードも非常に短いので以下にすべて掲載します。
<!-- KRPano Squash --> <krpano version="1.16" onstart="startup();"> <!-- 背景画像 --> <layer name="background" url="spacy.jpg" width="100%" height="prop" align="center" enabled="false" visible="true" zorder="10" /> <!-- パドル --> <layer name="paddle" url="paddle.png" width="80" height="15" align="topleft" edge="topleft" zorder="50" enabled="false" visible="true" /> <!-- 初期化処理 --> <action name="startup"> <!-- パドルの縦位置をセット --> sub( paddleY, stageheight, 50 ); copy( layer[paddle].y, paddleY ); <!-- メインループ呼び出し --> asyncloop( true, mainLoop() ); </action> <!-- メインループ --> <action name="mainLoop"> <!-- パドル移動 --> relocatePaddle(); </action> <!-- パドル移動 --> <action name="relocatePaddle"> sub( paddleX, mouse.stagex, 40 ); copy( layer[paddle].x, paddleX ); </action> </krpano>
KRPanoにはレイヤーという機能があります(かつてはプラグインと言っていました)。通常のパノラマVRでは画面上にポップアップを出したり、操作アイコンや地図などを表示したりするのに使用しますが、今回は背景画像やパドルのキャラクターを表示するのに使いました。昔なじみの言葉を使うならば、レイヤーはスプライトとして使用できるわけです。もちろん、パドルだけでなくボールや得点表示などもレイヤーを使うことで簡単に実現可能です。
そして、もう一つKRPanoに備わっている面白い機能が非同期ループです。このループはフレームが描画されるたびに一度回り、非同期で動作します。リアルタイムゲームにうってつけの機能ですね。パドルの位置書き換えはこの非同期ループの中で実行しています。マウスの座標に追従してパドルが動くように、パドルの座標を適宜変更する処理を書いています。
たった数十行のコードでこれだけの処理が実現でき、しかもPC、スマホ・タブレットなどのマルチデバイスで動作するというのは驚異的なことです。KRPano恐るべしといったところでしょうか。次回はさらにボールの動きを追加して、よりゲームらしくしていきます。
2014年4月26日
KRPanoスクリプトは簡易的なスクリプト言語ですが、プログラミング言語に必要な要素をひと通り実装しています。変数、条件分岐、繰り返し構造、関数定義、各種入出力など、仕様を見てみるとおよそ世間のプログラミング言語とそう変わらない機能ラインアップです。それどころか、プラットフォームを選ばずFlashでもHtml5でも動くという点では強力な汎用性を備えた言語であるとも言えます。
今回はそんなKRPanoスクリプトでオブジェクト指向風プログラミングを実験してみます。もちろん、KRPanoスクリプトはオブジェクト指向言語ではないので、諸々トリックで実現していくことになります。まずは、以下のコードをご覧ください。
<krpano version="1.16" onstart="startup();"> <!-- testクラスの定義 --> <class name="test" property="123" /> <action name="startup"> showlog(); <!-- class['test']のプロパティを表示 --> trace( 'show property:', class['test'].property ); </action> </krpano>
前回のサンプルコードとほとんど同じですが、独自タグの名前を<class>としているところがポイントです。もちろんKRPanoの標準タグの中に<class>などという定義はありません。つまり、これはKRPano上でクラス定義をしているつもりなのです。
KRPanoではすべての変数がグローバルスコープに配置されますが、上記のようにclassタグの中にpropertyを含めることでOOP的なカプセル化が実現できました(またname属性が連想配列として機能しているところもポイントです)。
色々なツッコミがあるかと思いますが、更に次のコードを見てください。
<krpano version="1.16" onstart="startup();"> <!-- testクラスの定義 --> <class name="test" property="123" action="trace('action called:', %1 );" /> <action name="startup"> showlog(); <!-- class['test']のプロパティを表示 --> class['test'].action( class['test'].property ); </action> </krpano>
クラス定義の中にメソッドを追加しました。これで一段階、オブジェクト指向らしくなります。
KRPanoの公式マニュアルによるとアクション定義は<action>タグを使用するとされていますが、実はこれは便宜的な仕様で必ずしも<action>タグである必要はありません。KRPanoスクリプトをご存じの方にとっては意外だと思われるかもしれませんが、例えばレイヤーのイベントハンドラなどでonclickプロパティにアクションを記述できることを思い出していただければ納得できるかと思います。
この事実は、KRPanoスクリプトが非常に柔軟な言語であることを意味しています。公式マニュアルには使用可能なタグの説明が出ていますが、実は言語的にはタグの定義名は何でもよく、識別子に「()」さえつければ、何でも関数として呼び出すという仕様なのです。また、KRPanoの世界では型がなく、全てが等しくオブジェクトとして扱われます。C言語風に捉えるならば、識別子は全てポインタで「()」は関数呼び出しの演算子という扱いなわけです。(正確にはオブジェクト内容を文字列として解釈し、関数とみなす演算子といったところでしょうか)
KRPanoにとって関数がただの文字列であるという証拠が以下のコードです。
<krpano version="1.16" onstart="startup();"> <action name="startup"> showlog(); set( function, 'trace( function called );' ); function(); </action> </krpano>
JavaScript風に変数「function」に関数定義を代入して実行することができてしまいます。なんと自由な言語でしょう。(無名関数の実装はできないみたいですが)
しかし、先ほどのソースコードをオブジェクト指向というには、まだまだ突っ込みどころがあります。このままだとスタティックプロパティやスタティックメソッドしかないクラスになってしまいます。次のコードではクラスのインスタンスを作ってみます。
<krpano version="1.16" onstart="startup();"> <!-- testクラスの定義 --> <class name="test" property="123" action="trace('action called:', %1 );" /> <action name="startup"> showlog(); <!-- インスタンス化 --> copy( instance1.property, class['test'].property ); copy( instance2.property, class['test'].property ); copy( instance1.action, class['test'].action ); copy( instance2.action, class['test'].action ); <!-- それぞれのインスタンスに値をセット --> set( instance1.property, 'def' ); set( instance2.property, 'ghi' ); <!-- それぞれを表示 --> instance1.action( instance1.property ); instance2.action( instance2.property ); </action> </krpano>
実装方法を考える中で一番悩んだのは、このインスタンス化です。というのもKRPanoには別段「new」コマンドがあるわけではないからです。その「new」の代わりに使えるのがcopyコマンドです。公式マニュアルによると、copyコマンドは変数の内容を変数にコピーする命令と書かれていますが、実はオブジェクトをコピーする命令です。変数にかぎらずあらゆるオブジェクトをコピーすることができます。内容が数値や文字列でなくとも、アクション定義ですらコピーできてしまいます。この性質を利用して、クラス定義をまるごとコピーすることでインスタンス生成を実現してみました。そういう意味ではよりシンプルに
copy( instance1, class['test'] ); copy( instance2, class['test'] );
とすればいいように思うのですが、どうも階層のあるオブジェクトの場合、実体コピーではなく参照コピーとして動作してしまうらしく、オブジェクトの実体が共有されてしまうようです。苦肉の策として、各プロパティ、メソッドごとにコピーするという手にしました。(あまりかっこよくないですが)
インスタンスが単なるクラス定義のコピーなので、これはどうもエセオブジェクト指向なのですが、言語仕様の柔軟さを利用するとこのようなことも実現できるわけです。コピーの方に別々のプロパティやメソッドを追加すれば継承もどきもできますし、なんとか使い物にはなりそうです(関数の引数は定義できないので、ポリモーフィズムは難しい)。
余談ではありますが、実装を考えながら「オブジェクト指向はプログラミングスタイルであって、言語仕様ではない」という教えを受けたのを思い出しました。
2014年4月21日
パノラマ再生エンジンのデファクトスタンダードとして、世界的にシェアの高いKRPanoですが、その大きな特徴の一つとして、スクリプティングを前提としていることが挙げられます。プログラミングに馴染みのないユーザには敷居が高く感じられる特徴でもあるのですが、一方でこのスクリプティングの自由度の高さのおかげで、パノラマコンテンツに多くの可能性を与えることができています。
さて、このKRPanoスクリプトですが、実はプログラマーにとっても難物です。基本的にはパノラマVRを定義するための設定スクリプトが発展してきたという経緯があるため、プログラミング言語としては、なかなかクセのある仕様になっているのです。例えば
- インタプリタが変数とリテラルを区別できない
- 変数・関数のスコープは全てグローバル
などの特徴があります。一つ目の件ですが、具体的には変数にリテラルを代入する場合と、変数の値を代入する場合で異なる命令を使う必要があります。
<!-- 変数にリテラルをセットする --> set( valA, 123 ); <!-- 変数に変数の値をセットする --> copy( valB, valA );
オペレータイコールで代入という便利な仕様はないので、変数操作時には都度setだのcopyだの書かなければなりません。(なんとなくアセンブラを思い出す作りです)これは関数の引数として変数の値を渡したい場合も同様で、以下のように記述しなければなりません。
<!-- 関数hogeの引数としてvalAの値を渡す --> hoge( get( valA ) );
普通のプログラムの感覚だとつい「hoge( valA );」と書いてしまうのですが、これだとリテラルで「valA」という文字列が渡るので値を取得することができません。私自身もこの仕様には何度もハマってしまい「あれー、ちゃんと渡してるのにおっかしいなあ。」という事が何度かあります。ただ、考えてみるとそもそも変数が全てグローバルなので、引数で変数の値を渡す意味はないのかもしれません。
こう書くと不自由な言語のように見えますが、KRPanoにはひとつ非常に面白い特徴があります。それはマニュアルに記載されているタグ以外にユーザー定義のタグを使うことができる点です。KRPanoの構文は基本的にはxmlになっているのですが、スクリプト上から任意のxml要素にDOM的にアクセスすることができます。
<!-- KRPano User Defined Tag Test --> <krpano version="1.16" onstart="startup();"> <!-- 独自定義のタグ --> <userdata attribute1="123" /> <action name="startup"> showlog(); <!-- 独自定義のタグからデータを読み込む --> trace( 'attribute1:', userdata.attribute1 ); </action> </krpano>
このコードで定義されている<userdata>というタグは、KRPanoで用意されているタグではなく独自に定義したものです。このタグに記述されている情報に、スクリプトからアクセスすることができます。
上記のように独自のXmlタグを定義することで、各種情報を自由にスクリプト上に配置することができます。さらに、参照ばかりでなく変更、ノードの追加についても、スクリプトから動的に実行することができます。このKRPanoが備えているDOMアクセス機能は非常に強力で、KRPanoに標準添付されるバーチャルツアーエディタやKolor社のPanoTourProなどでも、ツアー情報など内部的な情報を独自タグの形で展開して保存しています。弊社PanoCreatorのツアーエディタでは独自タグのデータ構造をJavaScriptを使ってサーバに送信し、ツアーデータを保存しています。
このDOMアクセス機能を駆使するとかなり高度なことができるのですが、どういうわけか公式マニュアルには特に記載されていません。
2013年7月24日
ドイツの思想家ヴァルター・ベンヤミンは、映画というメディアに対して、触覚的(taktisch)受容という言葉を用いました。一方で、絵画や写真を鑑賞することを視覚的受容とします。ベンヤミンは、触覚的に受容するメディアの例として、建築をあげています。なるほど建築物は、目で見て楽しむばかりでなくその空間の内部に入り、触覚的に体験することができます。映画が触覚的である理由の一つには、建築同様、そこに空間を感じることができる点があります。平面が2次元であるのに対して空間は3次元ですが、映画はフィルムを回すことによる時間軸の追加によって空間を現出させています。
映画の登場以前を振り返ってみても、パノラマやジオラマ、覗きからくりなどが目指しているのは空間の再現でした。様々なトリックやギミックを使って人間の知覚を欺き、平面を空間と見せかけようとしてきたのです。まさにバーチャルなリアリティそのものといえます。
同じく体験するメディアであるパノラマVRもやはり触覚的なメディアであると考えられます。パノラマVRの原理は、立方体や円柱の内部に二次元の画像を投影し、空間が広がっているかのように錯覚させることにあります。QuickTimeVRの産みの親であるAppleは、二次元から三次元空間を生み出すことをさして、バーチャルなリアリティと名づけました。パノラマVRはあくまでも平面のディスプレイを通してしか受容することができませんが、それでも我々は写真や絵画のようにパノラマVRを視覚的に鑑賞するのではなく、そこに映しだされている空間を体験することに価値をおきます。まさに「あたかもその場所にいるかのような」という言葉は、パノラマVRの価値を端的に表現した語であると言えます。近年流行しつつあるMotionVRは、パノラマVRに時間軸を加えることができる技術であり、さらに高度なリアリティを獲得する手段の一つであるといえるでしょう。(一方で、強制的に時間やカメラが流れていくため、使い方を間違えると「見せられている」感覚を受けるメディアでもあります。この他、MotionVRについてはまた別途考察したいと思います。)
そして、映画が物語性を獲得することによって、再現から表現のレベルへ繋がる新しい可能性を得たように、パノラマVRもまた単なる現実の再現にはとどまりません。ソフトウェアテクノロジーに由来するパノラマVRは、物理的制約のない無限の可能性を秘めています。Googleおみせフォトや各種パノラマガジェットの登場により、パノラマVRはより身近なメディアとなって来ました。より美しいパノラマあるいは、より現実に近いパノラマを突き詰めていく事と同時に、現実の再現を超えた新しい価値を付加していくことこそが、これからのパノラマVRが目指す未来であるといえるでしょう。
2013年6月24日
パノラマVRを表現する際、よく用いられる言葉に「体験」という語があります。「まるでその場にいるかのような体験」、「これまでにない新しい体験」、こうした言葉でパノラマVRは表現され、事実それは我々の感想を率直に表現していると言えます。ところが、パノラマVRとよく似たメディアである写真や映画を受容する事について、我々は「体験」とは表現しません。それらは「鑑賞」するものであって、「体験」するものではないというのが、一般的な感覚です。
同様に、19世紀のパノラマもまた「体験」するものであったと想像できます。壁面にぐるりと貼られた風景画はパノラマの道具立ての一つであって、それを絵画として鑑賞する事はなかったはずです。これら2種類のメディアの間に横たわる決定的な違いとは何でしょうか? その違いを端的に示すために少し遠回りをして、まずは映画について考えてみたいと思います。
実は、映画は当初「体験」するものでした。リュミエール兄弟が撮影した最初期の映画を 我々は今でもDVDやストリーミングの形で見る事ができます。工場から家路につく人々の様子や列車が駅に到着する映像など様々な日常の風景が映像として映し出されました。列車が到着する映像が流されたとき、観客は大騒ぎになったと言います。このエピソードは、映画がまさに体験であった事を示しています。
そしてこの映像は今なお体験的です。私は大学のイベントでこの映像をスクリーンで見ましたが、蒸気を吹き上げながら眼前に迫ってくる機関車には圧倒的な迫力とリアリティを感じました。19世紀の観客達と違って、私はそれが映像だと知っているので逃げ出したりはしませんが、少なくともその映像の本質はリアリティにあったように思います。
映画が鑑賞の対象となったのは、そこに物語性が生まれてからの事です。具体的には台本と編集、カメラワークが導入されてからの事だと考えられます。映画が物語性を獲得するまでには、ほとんど時間は要りませんでした。「水をかけられた散水夫」と呼ばれる作品が鑑賞の対象となった映画第一弾です。この映像ではホースで水をやろうとしている男性と、もう一人そのホースを足で踏んづけている男性のドラマが描かれています。ドリフの起源はすでに1890年代に存在していたようです。そしてこの映像は、上記の列車の到着風景などと同時に上映されました。つまり、映画はその登場時点から既に鑑賞対象となる可能性を内包していたのです。この後、映画は編集やカメラワーク、音声など様々な技術により表現手法の幅を広げ、より高度な物語性を獲得していきます。
鑑賞する映画と体験する映画の決定的な違いは、表現しようとしている内容にあります。列車の映像が現実の再現を目的としているのに対して、散水夫の映像は虚構の再現を目的としています。虚構とは作者の頭の中にある物語です。芸術論については専門ではありませんが、あえて言うならば芸術性の高いメディアが鑑賞の対象ということでしょうか。
パノラマVRが鑑賞の対象ではなく、体験するメディアである理由もこの違いによるところが大きいと思います。特に商業用途のパノラマVRは現実の風景を再現する事に重点を置きます。写真表現の芸術性の幾つかは、フレーミングや露出、ボケ味などにありますが、パノラマVRはこれらの表現と相容れません。全方位を収録するためフレーミングという概念は存在せず、全方位を接合した画像を生成するためにパンフォーカスで撮影するので、被写界深度の浅いボケ表現は使えません。
この違いは、何もパノラマVRがメディアとして劣っているというわけではなく、ある種の芸術性をカメラマンが決定しないというだけの話です。実は、パノラマVRにおいてフレーミングを決定するのは撮影者ではなく閲覧しているユーザであり、フォーカスを設定するのもユーザの視覚自体なのです。言い換えると、パノラマVRは作者の虚構という押し付けから解放された自由なメディアであるとも表現できます。この点については、インタラクティブという言葉がキーワードになります。
次回も引き続き、パノラマVRのメディアの特質についてさらに掘り下げていきたいと思います。
2013年6月10日
「パノラマ」という言葉は、18世紀末にロバート・バーカーという画家によって発明されました。彼はエジンバラやスコットランドの風景を極端に長く描いた絵画にパノラマというタイトルを付けました。絵画は半円状のキャンバスに描かれており、観客はその円の内側に立つことで、あたかも風景を目の当たりにしているかのように、絵画の世界を体験したといいます。非常に興味深いことに、パノラマはその登場時点から展示方法と密接に結びついていたのです。ちなみに当初のパノラマ作品は360度全周ではなく、180度の風景でした。
これまでの絵画とは一線を画する視覚体験に観客は魅了され、バーカーの興行は好評を博しました。人々の要望に後押しされ、彼は次々と新しい作品を発表していきます。ロンドン近郊ばかりでなく、遠くアテネやリスボンの風景もパノラマとして、観客の前に再現してみせました。さらなる体験を観客に届けるために、彼は世界初の360度全周パノラマ絵画を描きました。ロンドンのアルビオン製粉所の屋根からテムズ川を望む風景です。彼の展示には毎度たくさんの観客が詰めかけ、ついには専用の展示館を建設するまでにいたりました。ロンドンのライチェスタースクウェアにあったというバーカーの展示館は現存しませんが、現代には設計図が伝えられています。

展示館の図面に目を通すと、その設計には実に巧妙な演出が隠されている事が分かります。建物の入り口から展示室へ向かうには、観客たちはまず通路を通る必要がありました。暗い通路に目が慣れた頃、不意に観客の目の前には展望が開けます。眼前に広がるのは一面の異国の風景。観客はあたかも外にいるかのように錯覚します。ちょうど胎内巡りのように、暗い通路は異世界へと通じるトンネルになっているのです。
展示室の中にも、リアリティを演出するための工夫がいくつも用意されていました。例えば、観客の頭上にはひさしの長い屋根がつけられていました。上を見上げても屋根のおかげで絵画の切れ目が見えなくなっているのです。また、部屋の照明はわざと暗くされていたと言います。故意にディティールを見えにくくすることで想像力によってリアリティを補う効果を狙っているのです。(この技法は日本の覗きカラクリにも通じています)
パノラマはまさに登場時点からバーチャルリアリティのメディアだったのです。後年のパノラマ写真は、むしろPanoramic Photo(パノラマ的写真)であってパノラマそのものではないと言っても良いでしょう。また、どちらかというとパノラマ自体は絵画ではなく、興行であったことも注目に値します。たまたまリアルな風景を表現できる技術に絵画が存在しただけで、絵画としての芸術性とパノラマの価値は無関係です。パノラマの価値は、リアリティを演出するエンターテイメント性にありました。現代のパノラマVRを扱う我々にしても、この点は無視できないと思います。パノラマVRと写真の関係が、19世紀のパノラマと絵画の関係と相似していても不思議はありません。
次回は、パノラマVRの価値について考察していきたいと思います。
2013年6月7日
これから数回にわたり、弊社スタッフブログのコーナーを使って、パノラマにまつわるよもやま話を取り上げていきたいと思います。パノラマの起源や文化的特長といった点に注目することで、メディアとしてのパノラマVRについて考察できればと考えております。
まずは私自身のパノラマVR体験を振り返ってみたいと思います。私が制作したパノラマVRの第一号は2001年に撮影した自室のパノラマです。CanonのデジタルカメラIXYに付属していたPhotoStitchというステッチングソフトを使用しました。最初のデジカメをIXYにしたのも、このステッチングソフトが付属しているというのが理由でした。
以来、すっかり私はパノラマVR制作に魅了され、街中の至る所でくるくると周るだけでなく、イベントや旅行先には必ず三脚とパノラマ雲台を持っていき、せっせとパノラマを作り続けたのです。
私がパノラマVRを撮り始める数年前から、Web上ではQuickTimeVRを取り上げたサイトが見られるようになっていました。当時はまだ、小さなウィンドウで水平パノラマが表示されるだけでしたが、新しい視覚体験に大いに心を躍らされた記憶があります。
QTVRは基本的には横長の写真に過ぎません。いわゆるパノラマ写真は、QTVRどころかデジタルカメラが登場する以前から広く認知されていて、使い捨てカメラにもパノラマモードが存在していました。そして、我々は特にそのパノラマ写真をバーチャルリアリティであるとは意識していませんでした。ところが、1994年にAppleがこのパノラマ写真のデジタルビューワをQuickTimeに組み込んだ際に、彼らはそれをQuickTimeVRと名付けたのです。
それは一体なぜなのか、その謎を紐解くために次回はパノラマの歴史について触れたいと思います。