DATE: CATEGORY:三国志軍記開発
高さのズレが直った03
開発中のメイン画面
正確な高さが取得できるようになり、ユニットが空中に浮いたり地面に埋まらなくなった。部隊ユニットは個体毎に高さを取得し配置している。



◎高さ情報の出力

高さのズレを解消するため、高さ情報をテキスト出力して違いを確認します。

まずは地形作成プログラムの高さ情報をファイルに出力します。最初はコンソールに値を出力してコピペしようとしましたが、しばらく待っても終わらなかったので、結局C#でFileSystemObjectに出力しました。

XNA地形の高さ情報(テキスト形式)(0.6M)

次にメタセコイアの地形モデルから頂点情報を取得します。モデルの頂点情報を取得するのって結構ややこしいんですよね。

以前HPにまとめた記事を参考に頂点フォーマット(vertexElement)を確認したら、Position、Color、TextureCoordinate、Normalの4つでした。

そういえば、メタセコイアモデルの頂点フォーマットはXNAの標準構造体と合わないのでしたね。一応カスタム頂点フォーマットを作成して頂点座標を取得し、テキストファイルに落としました。

メタセコイア地形モデルの頂点座標情報(テキスト形式)(2M)



◎頂点情報の格納順序

ファイルは出力したものの、頂点情報はインデックス順で格納されているため、このままでは容易に比較できません(例えば、1番目の頂点情報が左上隅とは限りません)。

格納順序を解析して再展開するのも面倒なので、CSV形式で再出力しExcelでソートしました。

メタセコイア地形モデルの頂点座標情報(PDF形式)(7K)

参考までに4列目に行番号(=インデックス格納番号)を付けてからソートしたら、左上隅は1776番目、右下隅は5007番目の頂点でした。そういうものなんだ…。

ちなみに、X座標とZ座標は100倍して考えると分かりやすいです。細かい誤差があるのは、縦横2.56の大きさのマップを255で分解したからです(分解数を256にするとインデックスがオーバーフローするため)。



◎計算式を求める

ソートしたシートに先の高さ情報を転記し、高さ情報とY座標から適切な計算式を求めます。

頂点座標と高さ情報から計算式を求める(PDF形式)(11K)

まず、ある特定の頂点(ここでは左上頂点としました)と各頂点とのY座標差分や高さ情報差分を求め、それらの比率を算出しておよその倍率を24と決めました。次に、Y座標−高さ情報/24を算出し、およその差分を80と決めました。

つまり、メタセコイア地形モデルを100倍スケールで表示し、ユニットを「高さ情報/24+80」に配置すればズレがほぼ解消できるはずです。

しかし実際にやってみると、全然合いません。調べてみると、グレースケールのTerrain Bumpiness や Terrain Scaleプロパティの値が、データ出力プログラムと実行プログラムで違ってました。先にこれらを適当な値に調整してから高さ情報を出力すべきだったかも。

とりあえずプロパティを出力プログラムと同じ値にセットしてやり直したら、今度は合いました。

高さ情報計算式調整後

厳密に言うと、まだ若干の誤差はありますが、これまでの中では一番誤差が少ないと思います。

100%一致しない理由は不明ですが、Excelシートで微妙な誤差があったことを考えると、メタセコイアの地形作成機能は山の頂点を滑らかにするなどの調整がされているのかもしれません。



◎テクスチャマッピングのずれ

納得できる計算式が確立したので、地形モデル(分解数255)のテクスチャマッピングを行います。メタセコイアの範囲選択は座標指定できないので、縦横64マスを数えて範囲指定します。目が疲れる…。

作業を進めるうちに、端から中心までのマスが127個しか無いことに気付きました。そういえば、サイズは256だけど分解数は255でした。このままだと、テクスチャマッピングが若干ずれます。どうしたものか…。

A案:テクスチャの歪みを覚悟して続行する
   →見た目には気付かない?

B案:分解数128で作り直す
   →何かとバランスが良い
   →見た目が粗くなるので避けたい

C案:分解数252(63×4)で作り直す
   →最も無難?

D案:分解数256で作り直し、手動で頂点数を減らす
   →均一的な削減は困難
   →手間がかかる
   →グレースケールを再作成するとやり直し
   →パフォーマンスは向上する

E案:分解数256で頂点数を減らしたXNAモデルを作成する
   →マップの初期設定が遅くなる
   →作成工数がかかる
   →パフォーマンスは向上する

F案:分解数256で作り直し、頂点削減ツールを作成する
   →最も理想的
   →XNAでモデルのファイル出力は困難であり非現実的

頂点数を削減するとパフォーマンスが改善できるので少し悩みましたが、とりあえずC案を実施し、様子をみながらD〜E案への移行を考えることにしました。

尚、‘頂点数を減らす’とは『周囲の高さが同じ頂点を削除する』ということです。荊州マップは平原が多いので、かなり減らせると思います。



◎グレースケールのピクセル数

分解数252で再作成し、スケールを200倍で調整したのですが、いまいちズレるような気がします。

そこでまたプログラムを見直して考えたのですが、グレースケールのピクセル数は分解数+1とする必要があるのではないでしょうか?
というわけで、ピクセル数253、分解数252で試してみました。

メタセコイア地形生成オプション02   高さのズレが直った01

やりました!ピタリ一致しました!
半ば諦めかけてましたが、やっと直りましたよ〜!




いかがでしょう?丘の向こうから出現する騎馬隊とか、いい感じじゃないですか?



◎次回予告

次回は地形種別の取得です。これが終われば地形関連は一段落です。

ユニットの移動はまだ本格的にやりませんが、とりあえず川には入らないようにしたいですね。

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
漢水氾濫
漢水氾濫
三国志軍記のイベントCG。樊城攻防戦の序盤はホウ徳が善戦していたが、長雨により漢水が氾濫。機動力を封じられたホウ徳は、最後の決意を固める。



◎10月の目標達成度

・活動時間月160時間以上

実績:160h(達成率:100%)


・メイン画面の模索(48h)

実績:71hでユニット表示方式確定、地形3D化模索中(達成率:80%)


・全体スケジュールの見直し(12h)

実績:未着手(達成率:0%)


・ブログ更新/HP更新(50h)

実績:49hでブログ更新、「XNAの画面ハードコピー取得サンプルコード」作成(達成率:100%)


・別件企画(40h)

実績:28hでコンセプト等確定、システム案策定済(達成率:50%)


・その他(10h)

実績:12hでCG監修等実施(達成率:100%)


ユニット表示方式確が確定し、地形もあと少しで3D化できそうなので、10月はまずまずといったところでしょうか。



◎作業時間分析

作業時間集計2009年10月(PDF形式)

○良かった点
・後半はプログラム系が集中的に進んだ
・ブログ/HP比率がほぼ目標通りであった

○悪かった点
・前半サボりすぎて後半キツくなった(汗)
・別件企画の進捗が伸びなかった

9月の反動で10月前半はかなりペースが悪かったのですが、後半何とか盛り返しました(前半58h、後半102h)。

月間目標はなんとか達成したものの、少しは平準化しないと体がもちませんね〜。もし今月も同じような調子だったら、来月は中間目標設けましょう。


ところで、ジョギングはついに雨休みがありました。一度休むとサボりぐせが付かないか心配でしたが、とりあえず大丈夫そうです。



◎別件企画

企画内容は徐々に充実してきたのですが、相方都合によりしばらく延期となりました。再開予定は12月以降。

まだタイトルすら未定なので、無事に再開できるかちょっと心配ですね。シナリオも結局一人で書くことになったりして…。



◎進捗状況チェック

スケジュールは凍結中です。地形が確定したら、企画とスケジュールの見直しを行います。



◎11月の目標

・活動時間月160時間以上

・地形の高さ取得(16h)

・地形種別の取得(8h)

・企画見直し(24h)

・全体スケジュール見直し(12h)

・城モデルの画像取得/表示(16h)

・マップオブジェクト属性読込、表示(24h)

・ブログ更新/HP更新(50h)

・その他(10h)



◎次回予告

次回は地形の高さのズレを解消します。できれば地形種別も取得して、地形の作成/表示方式を確定させたいですね。

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
高さが微妙にズレている
開発中のメイン画面
地形の高さを取得してユニットの配置を調整中。まだ微妙にズレるようで、地面にめりこむ兵士が存在する。



◎XNAのバージョンアップ

今回は、地形の高さを取得してユニットの配置を調整します。高さ情報は地形作成プログラムで取得できるので、この情報をファイルに出力し、メインプログラムで読み込みます。

テキストファイル入出力は他の言語では簡単ですが、XNAではシリアライズとか同期とか面倒なことがあります。そのシリアライズですが、こちらの記事によると、XNA3.1のコンテントパイプラインでは自動化されたようです。

今回は自動化の恩恵に与れるか否か微妙なところですが、これを機にXNAを3.0→3.1にバージョンアップしました。一旦アンインストールしてからインストールしろとのことですが、インストールに1時間ぐらいかかります。あまり頻繁にはやりたくないなぁ…。

ちなみに、ネット接続状態で3.0の日本語ヘルプを起動すると、自動的に3.1の日本語ヘルプが追加されます。実は今までF1キーを押すと英語ヘルプが優先表示されていたのですが、今回から日本語ヘルプが優先表示されて快適になりましたw



◎ソリューションのアップグレード

ソリューション(プログラム)のアップグレードは任意です。

メインプログラムをアップグレードしたらそのまま動きましたが、ユニット画像取得プログラムをアップグレードしたらビルドエラーになりました。ACLのバージョンチェックではじかれたようです。

3.1版のACLはTEAさんがコンパイルしてくれていて、こちらのDLLを組み込んだら無事に動きました。

問題はSoftimageのランタイムで、こちらもプログラムをアップグレードするとビルドエラーになりますが、これに関する情報は見当たりませんでした。

XNA3.1でXNA3.0のプログラムがそのまま動くので、アップグレードしなければ当面不都合はありませんが、情報が無いのは不安です。このランタイムでゲームを作ってる人はACLよりも少ないってことなんでしょうね…。



◎使えません

アップグレードが完了したので本題に入ります。

グレースケールマップの高さ情報を一旦テキストファイルに出力し、それをメインプログラムで読み込むつもりでしたが、よく考えたら、既存のコンテントパイプラインでソレをやってるような気がしてきました。
実際に出力されるのはXNBファイル1つだけなので、いまいち確信が持てないのですが、この中にモデルデータと高さデータが混在してるはず…?

そこでまず地形作成プログラムのベースとなったHeightmapCollision(XNA公式サンプル)を複製し、コードを削りまくって高さ情報の受け渡し機能だけを残そうと考えました。高さ情報は最終的にModel.Tagに格納されますが、モデルデータは不要です。Model型からfloat型の二次元配列に変更したいのですが、これが私には難しくて…(−_−;


XNA3.1で自動XNBシリアライズ機能を利用する場合は ContentSerializerRuntimeType で型変更できるらしいので、ContentTypeWriter/ContentTypeReaderをコメントアウトしたらビルドエラーになりました。

多次元配列をシリアライズできません。

多次元配列の場合、自動シリアライズ機能は利用できないようです。わざわざバージョンアップしたのに…(T−T)



◎カスタムプロセッサの修正

仕方がないので自力で型変更を試みます。

Model.TagはObject型なので、Model→Objectに型変更してからfloatに変換しても良いのですが、問題はコンテントプロセッサの出力タイプです。ModelはModelContentが該当しますが、Objectやfloatに該当するものはありません。

そうなるとカスタムプロセッサを記述するしかなさそうですが、.xmlファイルを記述したり、ContentItemクラスを使用しなければならないのでしょうか?うーむ…。


…結局、HeightMapInfoContentを出力タイプに指定するだけで上手くいきました。元のサンプルはModelクラスの拡張プロセッサでしたが、こうすることで純粋なカスタムプロセッサになりました。

これまで散々悩んできましたが、ようやくカスタムプロセッサのプログラミングが理解できた気がします。



◎スケールの調整

新しいコンテントパイプラインプロジェクトと高さ取得メソッドをメインプログラムに組み込んでスケールサイズの調整を行います。これまでテキトーにやってたので、メタセコイアとXNAとユニットのスケールがなかなか合いません。

・マップを256倍すると端の座標がおよそ
 (-320,-320)〜(320,320)になるのは何故?
 →256×256の地形モデルを中心にずらして256倍したので
  256÷2×256÷100=327.68
  →(-327.68、-327.68)、(327.68、327.68)に
   ユニットを配置して目視確認OK

・マップの前後と左右でサイズが異なるように見える?
 →地形画像を2D正射影で取得した際に
  上下が少し切れていたため
  →当面無視

・ユニットが向きを変えると表示位置も変わる?
 →ユニットの原点位置を最大人数で調整しているため、
  人数を減らすと表示位置が変わる
  →ユニットの原点位置は、陣形毎&人数毎に
   調整する必要あり?

・GetHeightメソッドの有効範囲がおよそ
 (-320,-320)〜(180,180)で中心がずれている理由は?
 →GetHeightの中でint型に直してから計算しているため
  // left = (int)positionOnHeightmap.X / (int)terrainScale;
    ↓
   left = (int)(positionOnHeightmap.X / terrainScale);

スケールの調整



◎日本語のエラーメッセージ

スケールは概ね合わせたつもりですが、まだズレます。XNAとメタセコイアの分解数が異なるのが原因かな?

メタセコイアマップを分解数256で再作成し、XNAに取り込んで実行すると、日本語のエラーメッセージが表示されました。(従来は英語でした)

日本語のエラーメッセージ

わかりにくいメッセージですが、英語で出されるよりマシでしょう。

分割数を256×256としたらインデックスが16ビット(65535)をオーバーしてしまったので、分割数を254×254に落としました。

これでエラーは解消され、以前よりマシになった気がしますが、でもまだズレます。

分解数254



◎次回予告

放っておくと、ズレがズレを呼んでわけわからなくなるのがこれまでのパターンだったので、今回は徹底的に潰そうとしたのですが、まだズレます。こうなったら、正確な頂点情報を出力して1つ1つ比較しますか。

11月になったので、次回は「10月の総括と11月の目標」です。

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
深度バッファ設定後ユニット有
開発中のメイン画面
前回まで2Dだった地形が立体化した。見た目は良くなったが、課題もあるようだ。



◎地形の立体化

ユニットの表示方式が確定したので、今度は地形の立体化を試みます。

元々XNAで立体地形を作成したわけですが、地形種別を増やすとパフォーマンスが著しく低下してゲームにならなくなってしまうため、正射影画像を取得して板ポリゴンに貼り付けました。

これにより、上空から見ると立体的に見えるようになりましたが、地上から一人称視点で見渡すと平面だということがバレバレです。そこで、画像を板ポリゴンではなくメタセコイアの地形に貼り付けようと思います。

メタセコイアの地形は以前試したことがありますが、

・川などの地形種別が表現できない
・高さ情報を取得できない

この2点のために採用を諦めました。しかし今はこの2点を補うことができるので、改めて試してみようというわけです。



◎地形画像のマッピング

まずは、以前と同様にグレースケールマップから地形を自動作成します。

メタセコイア地形生成オプション

マップ画像を拡大して4×4=16枚にしたので、縦横の分割数も4で割り切れる数値(64)にしました。

次に、作成された地形にマップ画像を張り付けていきます。


1.マップ画像を読み込んだ材質を
  マッピング方式=平面で新規に作成

2.16×16個分の平面を選択

3.選択部処理→面に現在の材質を指定

4.マッピング機能で平面を選択し、シフトキーを押しながら
  マッピング基本図形を90度回転させて面の方向を調整

5.マッピング機能で選択面にフィット

  ※1マップ画像分完了

6.材質をコピーし、画像ファイルを差し替える

7.2、3、5を実施する
  (5を省くとXNAでおかしくなる)

  ※1マップ画像分完了

10.6〜7を繰り返す


メタセコイアで地形画像のマッピング

分割数を増やして起伏を滑らかにしたり、自動や手動で頂点数を減らすことも可能ですが、細かい調整は後にして、まずはXNAで試しましょう。



◎入れ替えテスト

というわけで、板ポリゴンを立体地形に入れ替えました。

立体地形に入れ替え   立体地形に入れ替えズームアップ

ふむ…。
カメラをズームアップしても山が立体的に見えますし、パフォーマンスも出てるので、基本的にはイケそうですね。

しかし、山の方は映像がおかしい所があります。正射影画像を3Dモデルに貼り付けた影響かもしれません。

それと、静止画ではわかりませんが、地形のスクロールとユニットのスクロールがズレます。
板ポリゴンと入れ替えただけなのに倍率を合わせてもズレるので不思議に思いましたが、実は地形立体化の影響で空中に浮いてました。

とりあえず平原の平均的な高さに合わせましたが、ズームアップした状態でスクロールすると結構ズレます。ちゃんと高さ情報を取得して合わせないとダメっぽいのですが、以前はユニットの原点が中央か足元かだけでズレが生じたことを考えると、シビアな精度が要求されるかもしれません。

大丈夫かなぁ…。



◎2Dマップ画像の取得

2Dマップ画像を取得するなら、フリーのマップエディタでもできそうです。

ちょっと悩みましたが、理想のマップエディタを探し当てるのも面倒ですし、自由に改造できる柔軟性も考慮して、既存のマップ画像取得プログラムを改造して一括出力しました。

正射影000   平面正射影000
元の正射影画像(左図)と2D正射影画像(右図)

2D画像は、マップの起伏を一律にならして正射影で取得しました。法線の影響のためか影が付いてますが、むしろ微妙な変化が面白そうなので、これで試してみましょう。

2Dマップ画像に差し替え(JPG)   2Dマップ画像に差し替え(BMP)
jpg画像(左図)とbmp画像(右図)

むむ…以前よりは良くなったようですが、山の映像はまだおかしいですね。

それと、jpgとbmpでかなり雰囲気が違ったので両方挙げてみました。jpgだとぼやけるのでbmpにしようとしたのですが、bmpの輪郭が黒いのは何故でしょうか?



◎黒い原因と対処

bmpの輪郭が黒い理由が判明しました。
黒い部分には透明度が設定されてました。

元の3Dマップは複数のパターン画像を重ね合わせているので、境界線に透明度が設定されます。これをbmpフォーマットで保存すると、自動的に32ビットで保存されてしまうのです。

XNAでは保存する際のビット数を指定できないので、C#でBMPファイルを32ビット→24ビットに落とすプログラムを作成しました。

テストコード

しかし、実行すると32ビットBMPが作成されてしまいました。クローン作成後の PixelFormat を表示すると、Format32bppRgb でした。Bitmap.Clone()の引数でフォーマットを指定しても、ビット数は減らせないようです。

仕方がないのでピクセル単位でコピーしました。ちょっと遅いのが難点ですが、頻繁に使うわけでもないからまぁいいか。

採用コード



◎深度バッファ設定

山の映像が乱れる問題ですが、深度バッファを設定してないことが原因でした。深度バッファを設定したら直りました。

深度バッファ設定後

映像的にはOKですね。あとは地形とユニットのスクロールのズレだけです。



◎次回予告

次回は地形の高さを取得してユニットの配置を調整し、スクロールのズレの解消を目指します。これが成功すれば地形の作成/表示方式も確定ですね。

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
複数ユニット表示方式変更後   複数ユニット表示方式変更後ズームアップ
開発中のメイン画面
部隊ユニットの表示方式を変更し、単体画像で人数分表示するようにした。画像やプログラムも併せて調整し、滑らかな画像と解像度を実現した。パフォーマンスも良好。



◎右利きと左利き

前回は取得した画像を全て使用しましたが、画像を反転すれば半分近く減らせますね。

でもちょっと待てよ?
画像を反転すると、武器を持つ手が急に切り替わって不自然に見える角度が出来てしまいます。これでは、画像切り替えの不自然さを軽減するために画像数を増やす意味が無い気がします。

というわけで、当面は反転画像を使用しません。



◎Immediateモード

画像取得プログラムを実行すると、何枚か画像取得に成功した後でエラーが発生することがあります。

保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。

発生場所は spriteBatch.End() です。再度実行すると、問題無く全画像取得できたりします。

時々発生するということは、タイミングの問題かもしれないと思い、レンダーターゲットを戻した後でウエイトを入れてみましたが、現象変わらず。

ウエイトを入れる場所が悪いのかなぁ?
それとも、レンダーターゲットとスプライトバッチの相性?

結局、spriteBatch.Begin() の引数の SpriteSortMode を Immediate → Deferred としたら、以後エラーが発生しなくなりました。レンダーターゲットを変更する際は、Immediate モードを使用しない方が無難なようです。



◎あちこち修正

槍兵の複数ユニット画像を取得してメインプログラムに組み込み、ついでにあちこち修正しました。(試行錯誤中のコードを整理したら5分の1ぐらいになりました(^_^;)

槍兵蜂矢の陣

実際に表示すると、気になることが出てきました。


1つは陣形。騎兵用の陣形は槍兵に相応しくないですね。

とりあえず槍兵は2列横隊にしましたが、陣系数が増えると画像数がさらに増えることになります。

容量低減のために、解像度を800×600→320×240に変更しました。ファイルサイズが4分の1ぐらいになりました。

32方向×10枚×約12KB×4陣形×10種類=約160MB

まだちょっとデカいですが、一応現実的なレベルになってきました。


もう1つ気になったのは、ユニットが浮いて見えること。

単体ユニットの時に同様の問題が発生しましたが、その時は板ポリの原点を中央最下部に設定しました。単体ユニットは通常その辺が足元になるのでうまくいきましたが、複数ユニットの場合、真ん中の兵士の足元の位置を原点とする必要がありそうです。

結局、ユニットの種類ごとに補正値を比率で設定するようにしました。また、単体ユニットの画像も32方向で取得して混在表示できるようにしました。

槍兵横陣   槍兵横陣ズームアップ

解像度を落としたので、カメラをズームアップするとちょっと厳しいですが、モデルが動いているので何とか耐えられるレベルです。



◎複数ユニットの表示方式について

単体ユニットを表示してちょっと驚いたのですが、単体ユニット32方向の画像切り替えは全然カクカクしないので、普通の3Dモデル表示と比べても全く遜色ありません。ここまで違うと、複数ユニットのカクカクを何とかしたくなってきました。

複数ユニットがカクカクするのは、各兵士の表示位置がずれるからです。画像数はこれ以上増やしたくないので、単体画像を人数分表示するようにしたいですね。

問題はパフォーマンスです。draw回数が10倍増えるわけですからね。でも解像度を落としたから何とかなるかも…?

試しに槍兵1000体表示してみました。

槍兵1000体表示テスト

さすがに12fpsでちょっとキツいですが、ゲーム中の1画面に部隊がこれほど集中することは滅多に無いので、結構イケそうな気がしてきました。



◎実装

というわけで、複数ユニットの表示方式を単体画像で人数分表示するようにしました。ついでに、1部隊の表示人数を1〜10人の範囲で指定できるようにしました。



おお〜凄い!
全くカクカクしません!パフォーマンスも出てます!画像を240×240でギリギリ収まるように調整したのでアップもOK!
ついにここまで来たか〜!!

ちなみに、陣形を増やしても画像数を増やす必要が無くなったので、ファイルサイズも低減しました!

32方向×10枚×約8KB×10種類=約25MB



◎次回予告

今回は画像取得プログラムの大活躍で調整が一気に進みました。(「出力→テスト実行→プログラム修正」を数十回繰り返しました。手作業でやったら死んでますw)

ゲームを作り始めてはや1年。解像度と滑らかさとパフォーマンスに四苦八苦してきましたが、ようやく満足できる状態になりました。応援して頂いた方々、どうもありがとうございました!

次回は城画像の取得、表示、地形の立体化などを行う予定です。今後も焦らず地道に頑張りますよ〜!

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

| BLOG TOP |

copyright © ゲーム制作の舞台裏 all rights reserved.Powered by FC2ブログ