テレワークならECナビ Yahoo 楽天 LINEがデータ消費ゼロで月額500円〜!
無料ホームページ 無料のクレジットカード 海外格安航空券 海外旅行保険が無料! 海外ホテル


log

2012.06.20 C++:地平線の描画

ファイル 401-1.jpgファイル 401-2.jpgファイル 401-3.jpg

今回はCryEngine風の海の表現が出来たらいいなと思い、手始めに地平線のラインを
描画してみました。…えーっと、「何故地平線?」って感じですね;

まずCryEngineの海の手法をザックリと説明します。CryEngineの海は無限平面の海
なのですが、ポリゴンが大量に使用されているのかと思いきや、ワイヤーフレームで表示
してみると実は数十ポリゴンしか使用していないことが分かります。ちなみに画像の2つ目
がCryEngineの元の画像、3つ目がワイヤーフレーム画像です。ワイヤーフレーム画像
のワイヤーはスカイドームのワイヤーと海面下の地面のワイヤーと残るはスクリーンに
平行なワイヤーの3つに分かれていますがその3つめのワイヤーが海面のポリゴンの
ワイヤーとなります。要するにスクリーン内の無限平面の範囲をあらかじめ求めて、
ポリゴン数を減らしている訳です。

この手法をやろうと思うと画面の地平線の位置を求める必要があるなと気が付き、
そういうことで地平線の位置の取得と描画の実装に至った訳です。

一応、地平線の高さの求め方も説明しようと思います。
まず、視点からスクリーン左上への方向のy成分の絶対値をY0、視点からスクリーン
左下への方向のy成分の絶対値をY1、スクリーン左上の高さを0、スクリーン左下の
高さをHとします。スクリーン左端に地平線が入る場合は、スクリーン左端の高さYは
以下で求まります。
・Y = H * Y0 / (Y0+Y1);
この式は衝突判定で衝突距離を求める式P = P0 + N * t;(P0がt=0のときの座標、
NがP0からP1への方向ベクトル、tが衝突時刻)の式と同じような感じで求まった
と考えてください。P0は0で、Y0/(Y0+Y1)がt部分、HがN部分です。
スクリーン内に地平線が存在しない場合は以下のようになります。
・地平線が画面の下:Y = H * Y1/Y0;
・地平線が画面の上:Y = -H * Y0/Y1;
スクリーン内に地平線が存在しているかどうかは左上、左下の方向のy成分が両方とも
正値もしくは負値かどうかで判断します。正値なら地平線が画面の上、負値なら
地平線は画面の下になります。で、同様の方法で右側の地平線の高さも求まります。

さて、それで(…長いですがこれでラスト)。視点が無限平面の上なら地平線の下側が
描画側、視点が無限平面の下なら地平線の上側が描画側となります。ちなみにCryEn
gineでは海面より上か下かで海上/海中と描画が切り替わっています。

無限平面、デフォルトで実装してほしい機能だと思うんですが…あまり需要ないのかな。

追記:
これだけだとカメラが90度回転した状態(首をかしげた状態)だとおかしくなることに
気づきました。それを修正するにはカメラが90度回転しているとき(つまりY0=Y1=0の
場合)には上側と下側で地平線の位置を求めれるようにすればいいはずです。
それと後は正射投影の場合、必ずY0=Y1になるためこれも別の処理を加えないと
いけない気がします。