DATE: CATEGORY:三国志軍記開発
柵06
開発中のメイン画面
柵は簡易モデル方式で実装された。静止モデルの傾きの問題は解決したが、パフォーマンスは低下したようだ。



◎柵の作成

前回コメントで、yohさんから「(ビルボードは)奥行き感の重要な物体を表現するには向いていない」と教えて頂きましたので、城は今後別の方式を模索します。恐らく簡易モデルを作成することになるかと思いますが、他の静止モデルはどうでしょうか?

というわけで、メタセコイアでシンプルな柵を作りました。

柵01

この程度ならモデルを直接置いてもパフォーマンス的に問題無さそうな気がしますが、これは奥行き感の無い物体なので、まずはビルボードで試してみましょう。



◎柵の表示

というわけで、柵の画像を取得して配置しました。

柵02   柵03

やはり、画面の左下や右下に位置すると、回転したような傾きになります。これはビルボードの傾きによるものなので、ビルボードを無くしてただの板ポリにしてみました。

柵04   柵05

画面の左下や右下に位置しても下手に傾いたりしません。



◎柵簡易モデルの作成

柵は奥行きが無いので、両面板ポリで十分かと思ったのですが、真上や真横から見ると消えてしまいました。消えるとプレイヤーに誤解されてしまう恐れがあるので、直方体に画像を張り付けた簡易モデルを作成します。

柵画像を直方体に貼り付け01

直方体に単純に張り付けると、こんな感じになるのですね。これだとよろしくないので、上面と側面の位置をずらしました。

柵画像を直方体に貼り付け02

上面については問題無さそうですが、側面がおかしいです。これは、横棒が縦棒の奥に存在しているからです。

柵の横棒は縦棒の奥に存在している

このままだと側面がおかしくなるので、結局横棒と縦棒の位置を合わせて簡易モデル用画像を再取得しました。


大したものではありませんが、一応HPのダウンロードコーナーに3種類の柵モデルをUPしておきました。



◎パフォーマンス

柵簡易モデルをXNAに実装しました。

柵06

真上や真横から見ても消えません。絵的には問題無いのですが、パフォーマンスが気になります。

板ポリ5枚16頂点の柵簡易モデルをマップ上に200個配置したら、30→20FPSに低下しました。ガーン!この程度でそんなに落ちるとは…。

いざとなったら両面板ポリに変更可能ですが、それはなるべく避けたいので、後日モデルインスタンシング技術によりパフォーマンス向上を図ります。



◎次回予告

見た目の問題は解決しましたが、パフォーマンスが予想以上に低下したのはショックでした。この程度のローポリぐらい、パフォーマンスを気にせずガンガン表示したいものです。

モデルインスタンシングをやる前に、サンプルモデルを複数用意した方が良いと思うので、次回は城の簡易モデルを作成します。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
城17
開発中のメイン画面
城の傾きや方向画像のカクカクを改善したが、スクロールするとまだ微妙な違和感があるようだ。



◎城の傾き

カメラを前後や高低に移動すると、城が逆に傾いてしまいます。

城08   城09
カメラを手前(左図)から奥に移動した(右図)

カメラを前方(奥)に移動したら、城の手前が浮き上がってしまいました。ビルボードで板ポリゴンを表示するとこうなるわけですが、映像的には、城の手前が沈んで城の上面が多く見えるようになるべきです。

傾きが逆であれば、ビルボードの回転軸の指定を変えれば上手くいくかも?

試しに Vector3(0, 0, -1) と指定すると、カメラのZ軸方向の移動に対してはいい感じで傾くようになりました。しかしカメラをX軸方向に移動すると、あらぬ方向に傾いてしまいます。

城10   城11

そこで今度は Vector3(0, 1, -1) と指定すると、カメラZ軸移動に対して傾きが固定され、X軸移動に対して傾きが自然になりました。しかし注視点を変更すると、あらぬ方向に傾くケースがあります。

出来そうで出来ないのは、もどかしいですね(−_−;



◎城画像の再取得

それにしても、同じビルボードのプログラムなのに、兵士は自然に見えて城が自然に見えないのは何故でしょうか?
私が気になるのは下記の2点です。

・兵士の画像は前面8割、上面2割なのに対し、城の画像は前面と上面の比率が逆転している

・兵士は前面、城は上面に注視している

試しに城画像を前面8割、上面2割で再取得しました。

城12   城13

一人称視点はマシになったようですが、上空視点は相変わらずですね。うむむ…。



◎カクカクの原因判明

試行錯誤を繰り返す過程で、別件の「カメラを移動して画面をスクロールさせるとカクカクする」原因が判明しました。

それは「(方向転換に伴う画像の)変化量が大きくて目立つから」でした。
…同じことを以前書いた気がします(爆)

すぐに気付けなかったのは、兵士をズームアップして画面に大きく表示された状態でスクロールしても、カクカクした印象を受けないからです。しかし、兵士のスケールを拡大するとカクカクします。

見た目の大きさは同じでも、画像が粗いと気付きにくいのかもしれません。



◎カクカクの解消

方向転換に伴う画像の変化量が大きくて目立つなら、方向画像数を増やしましょう。

まずは32枚から64枚に増やしてみましたが、まだカクカクします。そこで128枚に増やしたら、かなりスムーズになりました。

しかしこのまま単純に増やすと128×5=640枚になってしまいます。城門の数と向きはゲームに影響するのですが、映像的に表現するのは諦めた方が良さそうですね。

というわけで、映像的には4方向の城門で統一することとし、90度分の32枚だけ残して使い回すことにしました。



◎対策方針の検討

カクカクが解消されて大分マシになったものの、傾きの問題は未解決のままです。どうしたものやら…。

A案:この状態のまましばらく様子見

B案:ビルボードの角度改善を目指す

C案:上面中心の画像に変更する

D案:板ポリゴンを増やす

E案:簡易3Dモデルを作成して置き換える

F案:元の3Dモデルに置き換える

A案にしようかと思ったのですが、柵や森を追加する際に同じ問題で詰まってしまいそうです。簡単にできる案だけでも試してみましょう。



◎パフォーマンス確認

まずはF案。多分ダメだと思いますが、3Dモデルとビルボードのパフォーマンス比較ってことで。

城14

・ビルボード方式
 兵士無し:58〜60fps
 兵士あり:28〜30fps

・元の3Dモデルに置き換え
 兵士無し:10〜12fps
 兵士あり:8〜10fps

兵士ありでもさほど低下しないのは意外でしたが、城だけでこれほど遅くてはこの先ゲームになりません。映像的にはバッチリなんですけどね〜…って当たり前か(爆)

モデルインスタンシングなどのテクニックで改善は可能ですが、それをやるなら先にモデルを簡略化すべきでしょうから、今回はやりません。



◎画像の変更

お次はC案。上面中心の画像に変更しました。

城15   城16

上空視点は改善されたようですが、一人称視点だと城の後部が浮き上がってしまいます。円柱型ビルボードでは、上面と前面の両方を同時にサポートするのは難しいようです。

ゲーム難易度‘強’の場合、一人称視点固定にしようと考えていたので、逆に難易度‘中’‘弱’の場合、上空視点固定として、画像を使い分けるという方法はアリかも。若しくは、ボタンやキーを押すと視点が切り替わるとか?

画像枚数は増えますが、難易度で制限する場合は読み込み数を抑えられますね。アイデアとしては悪くないかも。



◎回転軸の修正

画像を使い分けると改善はされますが、傾きが逆であるという現象は変わりません。というわけで、B案にチャレンジ。

やはりビルボードの回転軸が気になるので、こんな感じで指定してみました。

Vector3.Normalize(new Vector3(0, 1, -1))

すると、カメラのZ軸方向の移動に対しては良くなりました。しかし、カメラを左右に回り込ませて注視点を変えると、あらぬ方向に傾いてしまいました。これはつまり、オブジェクトとカメラを結ぶ線に直角な上方向を指定しろってことですね?

Vector3 rotateAxis = Vector3.Normalize(billPos - mainMap.MapViewPos);
rotateAxis.Y = 1.0f - rotateAxis.Y;
rotateAxis = Vector3.Normalize(rotateAxis);


※Matrix.CreateConstrainedBillboard()の引数に上記rotateAxisをセットする



◎調整

城の内側の地面が透けていると城が浮いて見えるので、城モデルを修正して地面を追加しました。城やマップのスケールを考慮して、ユニットのスケールを小さくしました。仕上げに、ネームプレートの位置を修正しました。



う〜ん…ビミョ〜だなぁ(汗)
これでも大分マシになったんですけどね。

城が画面の右下や左下に位置すると、円盤が回転したような傾きになります。ビルボードや板ポリゴンを使用してる以上、これは仕方がないようです。ビルボードは大きなモデルに向かないそうですが、この城も大きくて向かない部類に入るのでしょうか?



◎次回予告

別の方式を模索するか、保留して次のテーマに移るか悩みましたが、城だけの問題であれば簡易モデルを作成した方が良さそうですし、静止モデル全般の問題であれば別の方式を模索すべきでしょう。

というわけで、次回は他の静止モデルを作成して、同じ現象になるか確認することにします。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
城07
開発中のメイン画面
ビルボードの城とネームプレートが実装され、ゲーム画面らしくなってきた。ネームプレートは城の前後関係を考慮して重ね合わされ、以前より読みやすくなった。



◎城モデルの画像取得

今回は城モデルの画像取得/表示です。

まず、画像取得プログラムを改修して、ACLモデル以外に通常モデルのスクリーンショットも取得できるようにしました。他にも、画像出力前に既存ファイルを一旦削除するとか、各種パラメータを一箇所にまとめるとか、細かい改修を併せて実施しました。


城モデルは城門の数によって5種類あるので、全ての画像を取得すると32×5=160枚になります。城門4つの城を使い回すことにする場合、90度分の画像で足りるので、たった8枚に減らせます。

パフォーマンス的にはその方が良さそうな気がしますが、調整は後で行うこととして、とりあえず160枚取得しました。



◎城データの読み込み

城を配置する前に、城データ(名称や座標を記述したテキストデータ)を読み込む必要があります。

データ読み込み機能は漢字表示機能と連動したものを過去に実装済ですが、漢字表示機能はひにけにXNAの改造版です。XNA3.1化に伴い、ひにけに版がアップデートされたので、こちらもアップデートすべきでしょうか?

ちょっと悩みましたが、既存プログラムが複雑なので今回は単純にコンバートしたプロジェクトを取り込みました。
とりあえず今は動けばいいや(笑)

しかし単純コンバート版を組み込んで実行すると「ファイルが無い」とエラーになりました。テキストファイルはC#で読み込むため、「出力ディレクトリにコピー」を「常にコピーする」に設定しておかないと、デバッグフォルダにファイルが存在せず、エラーになってしまうのです。

漢字表示機能に関係してるのかと思って原因調査に手間取りましたが、結局以前決めた仕様を忘れていたことが原因でした(爆)



◎城とネームプレートの表示

データ読み込み機能、漢字表示機能などを再実装し、城の位置の高さを取得して配置しました。

城01

高さはちゃんと取得できてますね。しかし静止画だとわかりませんが、スクロールするとカクカクします。アニメしないモデルだと目立つなぁ…。


城02   城03

ネームプレートを表示しました。城の位置は大体合ってるようですね。

しかし困ったことに、SpriteSortMode.Immediateを設定すると、スプライトバッチのDrawString()やEnd()でエラーになってしまい、他のソートモードを指定すると、非透過状態となってしまいます。

これは以前から悩んでいた問題ですが、どうしても原因がわからないのでスプライトを避けてました。しかしいよいよ実害が出てきたことですし、何としても解決しないといけません。



◎スプライトバッチ開始オプション

ヘルプを参照すると、
Immediate モードでは、グラフィック デバイス設定の衝突を発生させることなく存在させられるのは、1 つのアクティブな SpriteBatch インスタンスのみです。
とあります。グラフィックデバイスやスプライトバッチのインスタンスが複数混在してるのではないかとか、コンテントマネージャをオーバーライドしたことが影響してないかとか、いろいろ調べたのですが、結局はスプライトバッチ開始オプションの問題でした。

改修前:
spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.SaveState);

改修後:
spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront, SaveStateMode.None);

SpriteSortModeの中ではImmediateが一番早そうですが、この場合SaveStateMode.SaveStateとしないと、3Dモデルの描画が乱れるという不都合がありました。しかし今はビルボード方式により3Dモデルが単純化されたので、この問題は発生しません。

改修後の組み合わせにすると、無事に透過処理が行われ、負荷も若干軽減された気がします。

城04



◎ネームプレートの透明度

城やネームプレートが無事に表示されると、いろいろ気になる点が出てきます。

まずはネームプレートと文字の原点を左上から中心に変更し、上下と左右のサイズ比率や表示位置を調整しやすくしました。但し、表示位置は城の傾きやカメラ位置に連動して調整する必要があるので、城の傾きを修正してから最終調整します。

次に、ネームプレートが重なるとゴチャゴチャして読めないという問題がありますが、よく考えたら、背景が半透明では重なると読めなくて当然です。文字の左右を半透明とし、文字位置の背景は不透明としました。

ネームプレートの透明/半透明/不透明

これで幾分マシになったようですが、まだまだ読み辛いです。よく見ると、後方の城名が前方のネームプレートの手前に描かれ、文字と文字が重なっています。

これはつまり、カメラ視点で城の前後関係を把握して、後方の文字の手前に前方のネームプレートを配置(または描画)する必要があるってことですね。



◎城の前後関係

カメラと各城の距離を1つ1つ計算し、それらをソートして順序を把握しようとすると、面倒な上に遅くなりそうです。XNAでサクッとできないものでしょうか?そもそも城モデルはXNAが前後位置を把握して描画してるわけだから、そこから情報を取得できても良さそうな気がします。

そこで深度バッファを確認すると、これはレンダリングされた各ピクセルの深度を記録したものでした。ピクセル単位の情報では役に立ちません。やはり自前でやらなきゃダメか。

やむなく自前での実装を検討します。カメラと各城の位置関係により距離は取得できるので、問題はソートです。

…でも待てよ?距離を0〜1の範囲に縮小して深度を指定すれば、自前ソートは不要?

float layerDepth = Vector3.Distance(モデル位置, カメラ位置) / 最大距離(=マップの対角線);

※spriteBatch.Draw()の引数に上記layerDepthをセットする

城05   城06

無事ソートできたようです。こんなに簡単に出来るとは思いませんでした(^^;

ちなみに、左図は文字背景完全不透明バージョンです。
見た目がちょっとアレなので、透明度2段階バージョンとしました(右図)。



◎次回予告

画像を取得して表示するだけと思っていたのですが、実際にやってみると課題問題が予想以上にありました。まぁ、深度指定のコツとか収穫もあったので良しとしましょう。

次回は城表示関連の残課題に対応します。
城の傾きの修正が難しくて試行錯誤中。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
川への侵入不可
開発中のメイン画面
試験的に侵入不可チェックを実装し、川には侵入不可となった。最終的には地形種別毎に移動コストを加算し、部隊の移動速度に反映させる予定。



◎地形種別の取得

今回は地形種別を取得し、データ検証を兼ねて侵入不可チェックを実装します。

カラーマップ画像の色情報(地形種別情報)を取得するコンテントパイプラインは作成済なので、これをメインプログラムに組み込み、HeightMapInfoと同様に改修します。

次に、カラーマップの解像度やスケールを252で調整し、座標を指定すると地形種別情報を返すようにします。試しに幾つかの座標を指定すると、それらしい地形種別番号が返ってきました。

これで地形種別の取得は完了です。



◎侵入不可チェック

最終的にはA地点からB地点までの最短ルートを判定できるようにしたいのですが、今回はその前段階として侵入不可チェックを行います。

一番シンプルな方法は、移動先の座標のみチェックするという方法です。但しこの方法には2つの欠点があります。

1つは、移動量が2マスを超える場合、間に侵入不可地形が存在していたとしても無視される、という問題です。しかし今回のゲームスケールでは、1ゲーム時間で2マス以上移動するユニットは存在しないので、この問題は無視します。

もう1つは、斜めに配置された侵入不可地形(川など)に対角線状に侵入すると、越えることができる、という問題です。

川を超えてしまう

この問題を解決するため、斜めに移動する場合は縦横の隣接マスも同時にチェックします。



◎フィールド散策

移動先が侵入不可の場合、向きを変えるようにして実行すると、予定外の所で向きが変更されました。うーむ。

…原因調査でしばらくハマってしまいましたが、どうやら移動プログラムがおかしかったようです。いきなり川沿いに移動させるのは無謀だったかな?

とりあえず1ユニットをパッド操作で8方向に動かすようにして、フィールドを散策し、ユニットの周囲の地形を確認しました。

フィールド散策

ユニットの周囲の地形と地形種別番号が合いません。データがおかしいのかと思ってテキストに出力しマップと比較すると、データとマップは一致しました。

では何故見た目と合わないのか調べたら、現在表示しているマップテクスチャがズレてました。メタセコイアで地形を再作成した際に、テクスチャを絶対パスで指定してしまい、昔の正射影画像が表示されていたのです。…もっと早く気付くべきですね(爆)



◎はみ出しモデル

テクスチャ画像を最新版に戻したら、テクスチャの境界線が出現してしまいました。とりあえずその問題は後回しにして、フィールド散策を続行すると、少しだけずれてる感じ。カラーマップの解像度を253で調整すると、ピタリ一致しました。


しかしまた新たな問題発生。部隊ユニットの中央の騎馬は川に侵入しなくなったのですが、その周囲の騎馬は川にはみ出してしまいます。

袋小路への侵入

最終的には、橋を渡る際は縦陣で一騎ずつしか渡れないようにするつもりですが、それ以外の陣系で袋小路に侵入した場合の処理も考える必要があります。移動処理を本格的に作る際に実装する予定です。



◎川沿いに南下

侵入不可チェックが可能となったので、再度川沿い南下プログラムにチャレンジします。

…今度はうまくいったようです。しかしこのマップは川が多すぎて必ず袋小路でつっかえてしまうので、デモとしては面白くないですね。1つ気になるのは、道沿いに斜めに突っ切ってくれないケースがあることです。何故かなぁ?

…仕様上の問題でした。川と道がクロスになる場合、川が斜めに存在するので侵入不可と判定されてしまうのです。

移動元と移動先が道の場合、優先的に移動可能としました。これで道がある場合はちゃんと通るようになりました(冒頭図参照)。



◎次回予告

地形種別の取得は無事完了し、試験的な侵入不可チェックが成功しました。地形関連は一段落ですね。

次回は城モデルの画像取得/表示です。

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

| BLOG TOP |
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 |

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