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


log

2010.09.21 C++:とってもやさしい壁沿い移動の解説?


ひさしぶりの投稿ですじゃ。

最近めっきりと日記を書く機会が減っておりましたが、ここ1ヶ月くらいは
プログラムの方を進めてました。え?そんな変わってないって?苦笑

具体的には壁沿い移動、パーティ歩き、それと新しくキャラクターの
位置にスプライトを表示できるようにしてみました!
実質的には壁沿い移動にほとんど時間がかかってしまいましたね…。
ようやく壁抜けしない壁沿い移動を実装できて、色々と反省するべき点が
多かったので以下に少しまとめてみたいと思います。

まず壁沿い移動の実装を考えてみたときに、大抵の方が
真っ先に思い浮かぶのが、
0.壁との内外判定で衝突判定テスト
1.衝突予定の壁と移動線分を順番に衝突判定
2.1で衝突した壁で壁沿い移動
3.壁の範囲を超えていたら補正
だと思うのですが。ここでこのまま思いついた通りにプログラムを組んで、
for(衝突予定リストを順番に) {
if(衝突している) {壁沿い移動;break;}
}
としてしまった場合、なんと。壁抜けが発生してしまうんですねえ;

ここで問題になるのが2の線分と線分の衝突判定での精度の
問題でして。この衝突判定、ちょうど線分の頂点で衝突していた
場合、衝突していないとして返される可能性が高いのです。
つまり、壁の辺の間でぐりぐりと移動していると衝突していると
判断されるべきが衝突してないよウフフ、として判定されるために
壁抜けしてしまいます。

じゃあどうすればいいかと色々と考えてみましたが。このままだと
どうしようも無いので第3者の情報を借りてきてそれと比較することで
解決することにしました。具体的には、現在壁の実装方法は
地面のポリゴンが存在していない部分については壁という風に
実装しているのですが。。この地面の情報を元に、自身の
真下の地面のポリゴンの3辺とまず一度内外判定を行い、
2辺以上外に判定された辺が存在する、且つ1辺が壁の場合は
強制的に2辺で共有する頂点位置に設定することで無事
解決できるようになりました。(他にも色々と条件分岐が複雑
なのですが、ここでは面倒臭いので抜きにします苦笑)

それにしても、これにたどり着くまでに大分試行錯誤してしまいました。
途中「floatからdoubleにすると精度上がって直るかな?」なんて
考えたりもしましたが、現在既にほとんどの関数でfloatによる実装を
してしまっていて変更がとんでもなく大変な上に根本的な解決に
ならないと思うので。とりあえずやる前に解決できてよかったのでした笑。

2010.04.17 C++:3Dゲームキャプチャについて

今日はFraps以外の録画ソフトを片っ端からダウンロード、
インストールを繰り返していた訳なんですが、Fraps以外の
3Dゲームキャプチャソフトで全く録画できなかったのでなぜだろうと
しばらく悩み中でした。後になって、ひょっとしたらプログラムではなく
PC環境に不備があるのではないかと思ったので、別のPCで
試してみるとなぜか録画できたんですが、そのPCというのは
作業しているPCと違ってビデオカードがオンボードだったんです。
それで、これまた何故だろうと思い、ひょっとしたらDirectX SDKの
コンパネ設定をいじったせいかなと思ったので試してみると、
どうやらそれがビンゴでした苦笑。

分かったことはSDKのコンパネでDebugモードとDebugレベルを
設定しているとキャプチャソフトが3Dソフトに割り込むのを
拒まれるようです。ちなみにデバッグウィンドウで確認してみると、
新しいスレッドが立ち上がって、直に終了していました。

ただ、Retailモードにすると、もう1台の方で録画できたDxtoryという
キャプチャソフトが作業PCの方でゲームプログラムを認証しなくなったり、
DebugモードであってもFrapsだと録画できたりするので、一概には
いえない感じです。一応、Gregionというフリーソフトで制限無く
作業PCの録画に成功できたので、とりあえず良しといった感じです。

2010.04.16 C++:モーション切り替え


やっとこさモーション切り替え実装できたでよ!

簡単な作業かなと思いましたが、2日もかかってしまいました。
とりあえず苦戦したのが、1つのXファイルに複数のモーションを
格納する際、各フレームのオフセット行列もファイル間で共通して
いないと駄目なんですが、てっきり同じオフセット行列を吐き出して
いるものだと思ってバグを探していたので、それに時間がかかって
しまいました。出力するソフトにもよりそうですが、どうやら
モーションの先頭フレームをオフセット行列として使用するみたいですね。

それで、いざようやくモーション切り替えができるようになった
訳ですが、現状だとなんだかモーション切り替わり時間によって
すぐにモーションが切り替わったり、逆にゆっくり切り替わったり
してしまっています。これは、おそらくモーションの補完を線形補完で
行っているせいかなと思ったので、次回はモーションの
球面補完をやってみようと思います。

それにしても、Frapsの体験版だと30秒までしか録画できないんですね。。
それにFrapsのFPS数が落ちていないにも関わらずモーションが
Fraps起動前と比べて少しカクつくことを考えると、おそらく
FrapsのFPSは録画におけるFPSで、実際にPresent()して
描画しているFPSはFrapsによって省かれているような気がします。
とりあえず、他の録画ソフトを色々試してみようかな。

2010.04.14 C++:モデルを新しいモデルに差し替え

ファイル 266-1.jpg

今まで、新しくコンバートする作業が面倒でキャラクターをずっと昔に
出力したXファイルモデルを使い続けていましたが、そろそろ
モーション切り替えを実装しないと格好がつかないなと思い、
新しいモデルの方でXファイルを作成してみたものの。。

読み込んでみると、なぜかモデルだけ全く描画されないという問題が!!

色々試してみて、シェーダに渡す定数レジスタ数をオーバーした場合に
発生する問題だということが分かったので、とりあえずいらない
フレームを消して無事表示させたのはいいんですが、一度に
使用できるフレーム数が79個って少ないなあ。。まだ髪の
ボーンを分けていないので、どうしたものか。悩みます。。

とりあえず頂点テクスチャを使用して、テクスチャにスキニング行列を
格納させることでレジスタ数の問題を解決させることができますが、
一般的には頂点テクスチャは浮動小数点テクスチャを使用するので
サポートしていないGPUとかいくつかあるんじゃないかな、と思うわけです。

それともう一つ、新しいモデルにモーションをコンバートさせようと思い
LWのMap Motion2でhmotファイルを読み込もうと思ったら
なぜか強制終了してしまい、うまくいかない問題が発生。
LWさんは、モーション関係の不都合が本当に多いです。
とりあえずMotion Mixerでhmotファイルを読み込んで、
適当なキーにプロットすることでモーションをコンバートさせましたが
キーを適当に打ったばっかりに、プログラムの方で読み込んでみると
前よりもさらに下手糞なモーションになってしまいました。。

コンバート関係はできたら自作プログラムでやるのがいいんだろけど、大変だ。

2010.04.11 C++:トゥーン修正

ファイル 265-1.jpg

今回はトゥーンシェーダの細かい調整をしていました。
僕のプログラムでは、トゥーンは放物変換で求めたUVとトゥーン用の
テクスチャを用いて表現していて、この放物変換でUVを求めると
1次元でトゥーンUVを求めずに2次元でトゥーンUVを求めるので、
より綺麗に表現できるようになるんですが。実はこれには一つ
やっかいな問題があって。ライトの裏側がなっている部分は
UVの明るい部分をまたいでしまうため明るくなってしまう訳です。
これの解決方法がt-potさんのサイトにのっていたので、
さっそく試してみたのが画像の右半分のものです。

左半分の画像はキャラの左腕が不自然に明るくなっていますが
右半分の画像ではライトの裏面の部分でもきちんと暗くなってます。
画像だとあまり目立たないと思うかもしれませんが、動いていると
ちらちらして見えて結構気になるんです、これ。

それで一応t-potさんのサイトにのっている方法を試してみて
無事解決できたものの、実はこの方法もまた限定な解決方法
でしかないんです。。t-potさんのサイトに載っていたのは、
分かりやすくいえば、「裏面だから暗くすればいいじゃない」的な
アプローチなんですが、それだと例えばテクスチャの暗い部分を
明るい色に変更してリムライティングのような表現をしようとすると
おかしなことになるわけです。ただ、リムライティング的なトゥーンを
やりたい場合はリムライティングのシェーダとトゥーンを併用して
組めばいいので別に問題ないかもしれないですね苦笑。

あとはHSV変換を使って影の色表現をしていたのを、単純な
式で表現したりしてました。というか、これをやらなかったら、
命令レジスタがいっぱいで放物変換の修正処理が入れれませんでした笑。

2010.04.10 C++:カラーテスト

ファイル 264-1.jpg

今日はひさしぶりにテクスチャに描きこみしておりました。
モニタによってはテクスチャの色が飛んで見えたりしたので
それをモニタ2つ使って確認しながら作業していた訳です。
といっても、もうひとつのモニタはむかーし買ったテレビデオですが苦笑。

今回の画像は、たまたまデバッグ中にみんなでかけっこをしている
かのような面白い1枚が出来上がったので、思わず撮ってみました。

2010.04.07 C++:フレネル反射!

昨日ふと、手動ミップマップを使うことで水面のフレネル反射が
表現できるんじゃないかなと思いつき、さっそく導入してみることにしました。

結構サクサクっと導入できました!実際に試してみると
カメラの角度によっては結構不自然な感じになってしまいましたが
上からみた感じだとそれなりにそれなりな感じです笑。
動画を録画してみて思いましたが、そういえば”どうぶつの森”の
水面の表現もカメラから水平ラインで反射していたので、
ひょっとしたら同じテクニックで表現しているのかもしれません。

考察としては、あくまで擬似的なものですが手動ミップマップで
表現することで元々のミップマップテクスチャを別のテクスチャと
差し替えているだけなので、コストパフォーマンス0でフレネル反射を
表現できてしまうのが素晴らしいなと思いました。

2010.04.07 C++:今度は視錐台カリング

さっそく視錐台カリングを試してみました。実はまだ視錐台カリングの
ビューポート行列の生成がおかしいのか、視錐台よりも一回り
二回りくらいおおきく判定されているんですが、キャラの描画
スキップ時にスキニング行列の計算もスキップすることでだいたい
平均で60fps近くでるようになりました。というより、前回の
速度の問題はどうやらHDDの容量不足が原因みたいでした。

それと試しにオクルージョンカリングと併用したりもしてみましたが、
カリングできるときは早くなりますが、カリングできないときは
結構遅くなりますね、やっぱり。とりあえず、僕の中では
オクルージョンカリングは諸刃の剣のイメージです。

以下、結論を少しばかりまとめてみます。
・カリングするほどシーンが大きくない場合は、そもそも
 カリング判定処理をしない方が早い。
・シーンが視野より十分に大きい場合は、視錐台カリングで
 Zカリングを検討する。
・FPSゲームのように複雑に入り組んだシーンではさらに
 オクルージョンカリングを行うことでスキップ回数が向上する。

実は自作の算術計算回りも除々にSSE等を利用し始めてます。
早くなっているかどうかはほとんど分からない程度なんですけどね笑。

2010.04.05 C++:オクルージョンカリングてすと

視錐台カリングを実装するくらいならオクルージョンカリングを
実装したほうがいいのではないかと思い、試しに実装してみたのですが。。

うーん。早くなるどころかなぜか不思議なことになりました苦笑。

一応説明すると、オクルージョンカリングというのはバウンディング
ボックスもしくはバウンディングスフィアのような単純モデルを利用して、
あらかじめモデルが画面に何ピクセル描画されるかを計算して
描画ピクセル数が0なら描画のスキップを行うという技術です。
で、バウンディングボックスを用いてオクルージョンカリングを
試してみたんですが、なぜか画面に描画されるモデル数が
多いときのほうがフレームレートが上がるんですよ、これが。
・画面内にモデル0~3体:33FPS
・画面内にモデル4~10体:40FPS

自分でも訳が分からないのですが。。おそらくオクルージョンカリングで
ピクセル数をCPUに取得するためにはオクルージョン用プリミティブの
描画終了を待たなければならないので、この描画待ち時間が
描画しているときより描画していないときの方が長くなるのかなと
いうのが今のところの僕の仮説。けど、実際は何ともいえません笑。

それにオクルージョンカリングをするためにオクルージョン
プリミティブを余分に描画しているので、結局Drawコストが
モデル数倍になってしまい、僕の環境ではオクルージョン
カリングしないほうが処理が早くなってしまいました(なんだそりゃ)。

ただ、これはオクルージョンカリング前に視錐台カリングを
行い、視錐台に入っている場合はオクルージョンカリングの
チェックを行うことで対処できるのかな、と思ったのですが
なんだか2度手間のような感じです。。

まあオクルージョンカリング自体はZカリングのアプローチ以外にも
例えば敵キャラの視野用のオクルージョンカリングを用いて
敵の視線にプレイヤーがいるかどうかの正確な処理が行えたり
するので、結構有用なんじゃないかと思う訳です。

結局、まとめとしては色々試してみるのはいいことです、ということでした。

2010.04.03 C++:BGM切り替え

今までBGMを1曲ずっと流しているだけでしたが、新しくBGM切り替えが
できるようになりました。そろそろメニュークラスや本格的にシーン管理
部分に入りたいので、軽い下積みというやつです。

視錐台カリングをやろうかなとも思ったんですが。今のところ
GPUは余裕があって、CPU処理がパーティクル等の処理で重たく
なっているので、視錐台カリングをやるとGPUの負荷は減っても
CPUの負荷が増えるため、逆に重くなるんじゃないかなということで、
とりあえず保留にすることにしました。PCの性能を限界を見極めて
プログラムを組むのは色々と難しいなと思います。