ゲームプログラミング/3Dグラフィック/非平面スクリーン投影
本ページの目的

本科目『ゲームプログラミング』は、ゲームクリエイターのための教材ではなくプログラマーのための教材です。
本ページの目的

よって、単にゲーム用の3D-CGを作るだけなら、本ページの方法は不要です。また、ゲームで3D描画をしたいなら、Windowsの場合ならDirectXなど既存の3Dエンジンがあります。
本ページの目的

しかし本ページでは、「今は自分は3Dエンジンを作れないが、将来的には自分で3Dエンジンを作りたいなあ」とか思ってるような人を念頭においています(ただし、本頁ページの水準では、到底ですが商用の3Dエンジンの質には及びません)。
本文まえがき

本ページでは、まず、円柱面投影の透視投影を考えることにする。ここでいう「円柱」とは、正円の円柱とする(正円柱)。
本文まえがき

楕円柱は考えないでおく。
本文まえがき

人間の目の黒目(説明の簡単のため、読者は東洋人だとする)の部分は、それほど眼球に占める角度が大きくないのに、しかし視界の角度と、眼球の角度は一致しません。そして、視界の角度は広く、150度くらいはありそうなのです。
本文まえがき

疑うなら、ためしに片目だけ開いて、その目の両方横に数センチ離れた位置で、両指をチョコチョコと動かしてみてください。
本文まえがき

視界で150度くらいでは、同時に目に写ってしまいます。眼球に占める黒目の割合はもっと小さい数十度程度の角度なのに、しかし視界はそれよりもかなり大きいのです。
本文まえがき

このため、人体の片目のセンサー配置は、球面の半円に近いと思われます。
本文まえがき

しかし工業的には球面加工のディスプレイを作るのは経済的・工業的に困難なので、人間社会では、どうしてもリアルな視界を再現する必要のある場合、平面ディスプレイを3枚程度あわせた下記のような多面・複数面の配置によって、擬似的に球面を再現します。
本文まえがき

自動車教習所のシミュレーターのディスプレイが、そのように3枚の平面が並んだ配置です。
本文まえがき

左右の2枚のディスプレイにより左右方向の視界をカバーしていますが、上下方向のカバーは無視しています。このため、足元および上空は見えません。ですが実際の自動車の運転では足元と真上を見ないのが安全運転なので、問題ありません。
本文まえがき

さて、多面体ディスプレイの解析をするのが、自動車シミュレーターとしては一番正確ですが、しかしこれは1台のパソコンモニターはどうやっても再現できません(実験には3台ディスプレイが必要です)。
本文まえがき

そこで、擬似的にですが、本ページでは、円柱に投影したものを展開したモデルを考えます。(というのは建前で、先に円柱投影のモデルを記述して、あとから自動車シミュレータの技術を元の版の編集者が発見し、それに合うように記事を再編集しただけなのが実情である。)
本文まえがき

誤解のないようにいますが、円柱面に投影された映像を展開図にした平面は、実際の視界に写る景色ではありません。もし円柱展開図だとすると、顔の裏側まで映像が見えてしまいますので、不合理です。だから、円柱展開図すら擬似的なものです。円柱展開図のうち、人間の視界に写る前方だけを切り出したものによって、本ページでは擬似的に視界と見立ててシミュレーションしているに過ぎません。これでも視界側面での誤差はありますが、しかし平面ディスプレイ1枚における視界側面での誤差の無限大になる発散現象と比べたら、まだしも円柱展開図のほうが遥かにマシという、だけに過ぎません。
本文まえがき

一見よさげに見える円柱モデルですが、致命的な欠点があり、それは方向によって誤差が変わるので(横方向と縦方向で誤差が異なる)、ころがる被写体などの回転運動をうまく表現できません。なので、円柱モデルに実用的な価値は、ほとんど、ありません。
本文まえがき

実用性なら、平面ディスプレイのほうが遥かに上です。いっぽう円柱モデルは、あくまで平面ディスプレイの欠点を考えるための対比的なモデルに過ぎません。なので初学者はまず、一般の平面ディスプレイの理論に習熟すべきです。
本文まえがき

さて、そもそも、人間の目のセンサー自体が、平面ではなく、やや球面です。そのくせ上述のように、眼球に占める黒目の角度と、視界の角度とが一致せず、とても複雑です。
本文まえがき

なので、どうあがいても、平面ディスプレイに実際の景色を映すのは、無理です。
本文まえがき

編集者は「たぶん、人間の片目の視界は、球面センサーに近いんじゃないのかな?」と考えていますが、それはあくまで仮説や予想にすぎず、本当に球面かどうかはわかりません。ただし、少なくとも、人間の片目の視界が、絶対に平面センサーの平面フィルム的な視界でないのだけは確実です。
本文まえがき

なぜなら、もし視界が平面フィルム的な配置だとすると、何度も説明しているように、必要なディスプレイの幅が無限大になってしまうからです。なぜ無限大になるかというと、平面ディスプレイのページでも説明したと思いますが(版にも寄る)、計算式ではある被写体映像の投影先でのx座標やy座票を求める計算において、視界の側面では計算式の分母が0になってしまうのですが、片目の視界だけでも150度近くはあるので側面に近い場所を移すことになり、このため必要なディスプレイの幅が片目だけでもとても膨大になってしまい、家1件よりも大きなディスプレイが必要になりかねず、不合理です。
本文まえがき

まして両目の180度をこえた視界をディスプレイ1枚で再現するとなると、真横の場所に対応するディスプレイ投影先のx座票が無限大になり、とても不合理です。
本文まえがき

実は、ゲームの3D映像は、リアルな3D計算ではなく望遠レンズぎみの構図を計算した映像です
本文まえがき

なぜ望遠かというと、平面投影におけるカメラ側面付近での投影座標の無限大発散の問題を無くすために、そもそも視界そのものを狭めるために望遠の構図にしています。
本文まえがき

さて、そのような望遠パースを採用しているゲームでは、ゲームプレイヤーを楽しませるための臨場感として、あたかも被写体がカメラ近くにあるかのような演出が必要であるので、なんらかの方法でゲームでは演出的なウソをついており、実際の視界に移る映像の再現ではありません。
本文まえがき

ゲームとしては、それで合理的です。「リアルとリアリティは違う」というヤツです。
本文まえがき

しかし運転シミュレーターでは、望遠テクニックによる視界の限定は許されないですし、視界の映像における演出的なウソも最小限にとどめなければなりません。このように運転シミュレーターには、ゲームにはない特有の難題があります。
本文まえがき

円柱モデルで解析とシミュレーションしたときに得られる知見として、
本文まえがき

側面 90° の位置での誤差の発散の問題があります。
本文まえがき

なお平面モデルでは、そもそも最初から側面の描画をあきらめていますので、この知見が得られません。
本文まえがき

数学で三角関数というのがあり、理系の大学で逆三角関数を習います。
本文まえがき

円柱モデルにて、素直に正面向きのときの進行方向を基準に側面の映像を計算していくと、計算式中に
本文まえがき

のような項が出てきます。
本文まえがき

これは、数学的には問題が無いのですが、しかしコンピュータ計算では誤差が莫大になり発散してしまいやすいのです。(疑うなら、実際に後述の計算式のとおりにプログラミングして試してください。側面90°で描画が異常になります。)
本文まえがき

誤差の発散の原因はおそらくですが、cos 90 ° が 0ですので、それぞれの微小誤差の影響が相対的に大きくなり無視できなくなり、発散してしまう空だろうと思います。
本文まえがき

もし円柱モデルを使って、この発散を無くしたいなら、
本文まえがき

側面の計算をするときは、けっして正面向きからの角度位置を基準にするのではなく、
本文まえがき

最初から90°横を向いた向きを基準にして、角度を計算しなおすことです。
本文まえがき

これは回転行列の計算で簡単に出来ます。
本文まえがき

なお、偶然でしょうが運転シミュレーターの設計でも必然的に、側面ディスプレイでの被写体の計算には回転行列を使って計算することになるでしょうから、運転シミュレーターの3枚ディスプレイでは誤差発散の問題は回避されることになります。
本文まえがき

あるいは、言い方を変えるなら、もしも正面パネルの中心向きを基準に極座標的にコンピュータ計算してしまうと、たとえ多面体モデルであっても、両側面での計算で誤差が発散してしまいます。
本文まえがき

だから、多面体モデルにて誤差を発散させないための対策としては、
本文まえがき

などの必要があるでしょう。
本文まえがき

ともかく上述のように極座標的なモデルや解析は、CGでは本ページで述べるように誤差の問題が生じるので、モデルが円柱モデルか多面体かに関わらず、プログラム中での数値計算の実用には極座標的なコードは適さない場合があります。
本文まえがき

仕方無いので、直交座標では人間視点での数学的な角度関係の見通しや把握は悪くなってしまいますが、しかし誤差を防ぐためになるべく直交座標の考えにもとづくプログラミングが3D計算では必要になるでしょうか。
数学的な内容

実際の被写体の図形は3次元だが、説明の簡単化のため、二次元平面中での線分をもとに説明する。
数学的な内容

円柱投影の場合での3D-CGの原理は余弦定理である。『高等学校数学I/図形と計量#余弦定理』
数学的な内容

被写体の2点(仮にAおよびBとする)から、それぞれの点の位置をあらわす座標(直交座標)をもとに、カメラの位置(仮にK)から被写体の各点のベクトル(KA: K A → {\displaystyle {\vec {KA}}} および K B → {\displaystyle {\vec {KB}}} )を得ればいい。
数学的な内容

そして、 K A → {\displaystyle {\vec {KA}}} および K B → {\displaystyle {\vec {KB}}} のなす角度θが求まる。
数学的な内容

あらかじめ、視野の角度θ0を、決めておく。
数学的な内容

あとは、θ0とθとの比率で、視界でどれだけの長さに投影されるかの比率をもつかが、求まる。
数学的な内容

また、基準となる点や線を用意しとけば、それとの角度差から、被写体の表示される位置も求まる。
数学的な内容

上記の計算で、仮にカメラを位置はそのままで、向きだけ変更させてみたとしましょう。つまり、カメラの向きだけ、右回りまたは左回りに回転した場合を考えます。
数学的な内容

すると、じつは、ある被写体の全身が視界の内部にあるかぎり、カメラの水平方向の回転量にかかわらず、じつは(余弦定理で単純計算した場合の)物体の見える大きさは、不変です。
数学的な内容

なぜなら、上記の条件でカメラの向きが変わっても、被写体の視野角に占める大きさが不変だからです。
数学的な内容

このため、たとえば、カメラの水平で右回りに回転させても、実は被写体の大きさはそのままで、単に被写体が左側に移動するだけです。(近くにある被写体ほど、大きく移動する。)
数学的な内容

被写体の見える大きさは、視野角に占める割合で決まるのですから、視界の中央にあろうが、視界のすみっこにあろうが、視野角に占める割合が変わらないので
数学的な内容

しかし、みなさんは日常生活では、目の前にあるものは、なんとなく大きく見える感じがしていると体感していたでしょう。
数学的な内容

同様に、日常生活では、視界のすみっこにある物体は、なんとなく小さく見える感覚があるでしょう。
数学的な内容

つまり、皆さんの体感と、数学の幾何学的な事実とは、ちがいます。
数学的な内容

この原因は、おおまかに、
数学的な内容

以上のことなどが、起因しているのでしょう。
数学的な内容

さて、3Dグラフィック的には、この事が分かると、いろいろと便利です。
数学的な内容

まず、被写体に奥行きの無い場合、つまり、被写体が平面物体の場合は、そもそも、いちいち三角関数をつかって計算をする3D計算の必要はありません。
数学的な内容

どういうときに3D計算が必要かというと、被写体に奥行きがあり、その被写体をさまざまな角度から見たい場合に必要になるのです。
数学的な内容

なので、もし被写体を一定の方向からしか見ないならば(たとえば、つねに南側にいる観測者が北側を見る視点ならば)、単なる、三角関数を使わない表現でも、充分にリアリティのある表現が可能なことが、数学的にも証明されることになります。
数学的な内容

このような数学的な事実がありますので、3Dグラフィックのプログラムを自作する前に、はたして自分に三角関数による3D計算が必要かどうかを考えておきましょう。
数学的な内容

なお、人間の首のかたむきや動き方の話の暗黙の前提として、人間が横を見たり振り返ったりする場合は、まず、肩や胴体はほとんど動かずに首(と頭)だけが動いて、そのあとに引きづられる形で、肩が動きます。これは、アニメーターの描く、人物の振り返りの作画の基本でもあります。
数学的な内容

さて、余弦定理でつくる角度が、回転しても変換というのは、中学~大学の数学で考えてみれば当然です。
数学的な内容

中学生レベルで考えれば、まず、三角形を回転して別の場所に位置を移動しても、移動先の三角形はもとの三角形と合同なままです。
数学的な内容

大学レベルで回転行列を使って考えれば、これは「回転行列は、2個のベクトルのつくる内積の値を不変に保つ」という定理へと一般化されます。
数学的な内容

さらには、『直交行列』といわれる種類の行列は、2個のベクトルのつくる内積を不変に保つという定理が、すでに解明されています。
数学的な内容

3D-CG製作で大切なことは、日常的な感覚と、上述の数学的な計算や定理との食い違いを、認識することでしょう。
数学的な内容

もし、ある若者が、数学を勉強していて直交行列の内積不変の定理だけを知っていても、それをプログラミングの場で本書のような予備知識なしで初見で「カメラの位置をそのままで視点の向きを変えても、被写体の見える大きさは変わらない」という事実に気づける人は、そう多くないでしょう。
数学的な内容

3D-CG そのもののビューワーなどのアプリケーション製作に必要な数学力とは、こういう「気づき」のできる能力のことでしょう。けっして単に、直交行列の公式だけを知っていても、それだけでは役立たずになってしまいます。
数学的な内容

もし正円柱に投影するのではなく、楕円柱に投影する場合を考えると、算出すべきは角度ではなく楕円弧の弧長である。
数学的な内容

正円の場合、角度のラジアンから弧の長さを三角関数によって簡単に算出できるので、角度さえ算出できれば、あとは高校レベルの簡単な計算で処理できるというワケである。
数学的な内容

数学的には、高校3年~大学1年の微分積分で習う「楕円積分」という積分の公式で、コンピュータ数値計算の手法で楕円の弧の長さを求めることができる。だが、楕円積分の解析は難しい。
数学的な内容

なおC言語では国際規格上ではC++などの規格で楕円積分を cmath ヘッダでサポートしているが、だが実際のC言語界隈では情報が乏しく、教科書が乏しいので、あまり使わないほうがイイだろう。なおC++の規格では comp_ellint_1 などで楕円積分を定義している。その他の数学の特殊関数もC++では規格上は定義されている。)
数学的な内容

なお、数学では、三角関数の楕円バージョンである楕円関数というのがある。楕円関数と、楕円積分の公式は、異なる。
数学的な内容

円柱投影であっても、カメラから見て真横に近い方角にある被写体などは、ケタ落ちのため、不正確な表示になりますので、対策が必要です。
数学的な内容

対策として、視界の中央から、±90°より大幅に未満(たとえば ±60°までなど)の一定範囲の角度内にある被写体だけを描画する必要があります。
数学的な内容

このため角度計算が必要ですので、被写体が水平方向から見て、その方角にあるかの角度を保存しておく必要があり、その角度が視界内に相当する一定の範囲内にあるときだけ描画するようにプログラムを記述する必要があります。
数学的な内容

どのみち、カメラの裏側にある物体の表示を隠したりするためにも、カメラから見た方角の角度の保存が必要になります。
数学的な内容

なお、カメラの裏側にある物体が映るのを隠すなら、反対方向のベクトルどうしの内積がマイナスになることを利用すると、計算が簡略になります。
数学的な内容

つまり、カメラの向きの単位ベクトルと、観察者から被写体への向きの単位ベクトルとの内積です。この内積が、カメラの裏側ではマイナスになります。
数学的な内容

90°の直交する2つのベクトルどうしの内積は0ですし、90°に近い角度で交わるベクトルどうしの内積はゼロに近い数字です。
数学的な内容

なので、たとえば「内積が 0.1以下の被写体は、描写を除外する」などのアルゴリズムを組めば、カメラ横にある被写体 と カメラ裏側の被写体 の描画を、同時に排除できます。
数学的な内容

ただし、内積を計算できるようにする前提として、0ベクトルを排除する必要があります。なので、カメラから一定以上の距離を判定基準として、その距離よりも離れた位置にある被写体だけに、このアルゴリズムを適用する必要があります。この判定基準の距離には、投影面の円柱の半径に近い数字を判定基準にすればよいでしょう。
数学的な内容

さて、この 横方向ケタ落ち 等の問題のために、円柱投影であっても、至近距離にある被写体などの描画では、平行投影に切り替えるなどの対策が必要になります。
数学的な内容

カメラの横方向にある物体も、平行投影に切り替えるなどの対策が必要になります。
数学的な内容

なぜなら、どんな被写体でも、カメラとの距離が0近くになれば、視界の±90°近くに入り込むようになってしまうからです。
数学的な内容

ケタ落ちの問題のため、どんな形状の投影面であっても、透視投影を使うかぎり、スクリーンとカメラの距離は、けっして0にはできません。
数学的な内容

このため、距離の遠近の判定をする必要があるので、判定基準としてカメラと投影面との距離の計算(これは投影面の円柱面の半径となる)が必要です。
数学的な内容

結局、スクリーンとカメラとの間の距離は、0にはできず、大きさを持った値になります。
数学的な内容

なので平面投影でも円柱投影でも、スクリーンとカメラの距離は、けっして0にはできません。
数学的な内容

さて、円柱投影では、水平方向では投影面は円ですが、垂直方向では投影面は直線です。このため、垂直方向の倍率は、平面投影と同じ計算式になります。
数学的な内容

もし、垂直方向の倍率も、水平方向の円投影の場合の倍率と同一にしてしまったら、それはもはや円柱投影ではなく球面投影ですので、地図の投影法(中学高校の社会科の地理で習うアレ)と同様の問題点に遭遇することになります。
自動車シミュイレーターとの関係

さて、私たちは円柱面の投影を考えましたが、しかし実際の自動車教習所にある3面ディスプレイは円柱面ではなく、
自動車シミュイレーターとの関係

平面ディスプレイを3枚、
自動車シミュイレーターとの関係

の配置で並べているのでした。
自動車シミュイレーターとの関係

円柱面の理論と照合してわかることは、なんと、教習所ディスプレイでは、実は、映像の精度が、3枚それぞれのディスプレイの中央部と両端部とで違います。
自動車シミュイレーターとの関係

もし3面ディスプレイが一般的な平面ディスプレイ用のアルゴリズムを使って3D表示してるなら、実は、各ディスプレイの両端部は、映像の精度が少しだけ悪いのです(なぜならディスプレイ形状を円柱面にしない限り、観測者からの距離は一定ではないので、精度は悪くなる。)この文脈での「精度が悪い」とは、位置が微妙に違っていたり、精密な前後関係が信用できないということです。
自動車シミュイレーターとの関係

おそらく、各ディスプレイの中央どうしに距離は、ほぼ一定になるように配置していると思われます。なので、私たちの考察では、各ディスプレイの中央から運転手の距離を基準にしましょう。
自動車シミュイレーターとの関係

すると、ディスプレイ両端部と運転手の距離が、基準よりも長いので、(前後関係などの)精度はすこし悪くなります。
自動車シミュイレーターとの関係

模式的に、下記の図に、拡大して、中央ディスプレイと右ディスプレイを抜粋して、精度の良否つきで書くと
自動車シミュイレーターとの関係

のような感じになるはずです。
自動車シミュイレーターとの関係

某社の運転シミュレーターのwebサイトの映像を確認したところ、ディスプレイ中央の映像と右ディスプレイの映像には、端部にすら重なりはありません。なので、2枚のディスプレイで精度を補強するようなことはしていません(もっとも、もし補強したらしたで、こんどは視界が狭まるという欠点もある)。
自動車シミュイレーターとの関係

これはつまり、原理的には、各ディスプレイの端部には、中央部ほどには精度を高く要求するギミック教材は配置できない可能性があります。
自動車シミュイレーターとの関係

ただし、ディスプレイが比較的に大きいことなどから、そんなに誤差は大きくないと思われます。なので、あまり気にしすぎる必要もないでしょう。
自動車シミュイレーターとの関係

また、この誤差の問題はけっして3枚ディスプレイシミュレーターだけの問題ではなく、実は1枚ディスプレイシミュレーターでも同様に、前セクションなどで述べた数学的な定理から、両端部の精度は微妙に悪いことになります。
自動車シミュイレーターとの関係

1枚シミュレーターと比べて3枚シミュレーターが向上している部分は、視界の広さです。残念ながら(映像オブジェクトの位置や前後関係などの)精度は向上できていないと思われます。
自動車シミュイレーターとの関係

やはり、シミュレーターはけっして本物ではなく、あくまで模倣にすぎません。だからあまり映像を信用しすぎることなく、最終的には、教習所の屋外の運転コースでじっさいに運転練習をするしかありません。
自動車シミュイレーターとの関係

なお、別ノセクションでも指摘してるかもしれませんが、実はCGでなく実写のビデオ映像だとしても、実は端部は誤差があります。レンズの仕組みやセンサーなどの仕組みにより、実写ですら、どうしても誤差が出てしまうのです。だから実写の撮影では、被写体をなるべく真ん中に近づける必要があるのです。
自動車シミュイレーターとの関係

だから別に、けっして「CGだから誤差がある」とかいうわけではなく、そもそも機械による映像の再現には誤差があるのです。
自動車シミュイレーターとの関係

よって、最終的には実際の運錬でなれるしかありません。
自動車シミュイレーターとの関係

一般の平面投影3Dでは、実はやや望遠ぎみの構図にすることで、両端部の誤差を少なくするテクニックがよく用いられます。
自動車シミュイレーターとの関係

しかし運転シミュユレーターの場合、(なんとか可能だとしても)望遠は困難でしょう。
自動車シミュイレーターとの関係

なぜなら、シミュレーターの用途である以上、実際の運転の視界をなるべく正確にシミュレートする必要があるのに、なのに実際の視界とは異なる望遠レンズのような構図にすることは許されないからです。
自動車シミュイレーターとの関係

また3面デイスプレイの場合、仮に真ん中ディスプレイだけ望遠にできても、それを両脇のディスプレイ映像とどのように整合性を取るのか、難しいでしょう。
自動車シミュイレーターとの関係

ともかく、3面運転シミュレーターでは、望遠テクニックは困難でしょう。
自動車シミュイレーターとの関係

なお、デイスプレイの両端部が誤差が大きいのは別に3D-CGに限ったことではなく、実は実写の映像も端部は誤差が比較的に大きいのです。
自動車シミュイレーターとの関係

だからテレビ撮影などの映像は、大きめのビデオカメラで撮影しており、誤差の大きい上下左右の端部をあらかじめ捨てた映像が放映されていると言われています。テレビ編集用の機材が、すでにそうなっているらしいです。
自動車シミュイレーターとの関係

だから教習所シミュレーターのディスプレイが大きいのも、そういった理由があるのでしょう。ディスプレイがなるべく大きいほうが(実写でいうビデオカメラのレンズが大きいこと相当するので、)誤差が減らせるはずです。