プロフィール

Na-7

Author:Na-7
SE(システムエンジニア)として約15年間システム系ソフト会社を勤めあげ、2008年3月退社。現在、ゲーム制作会社設立を目指して活動中。


アクセスカウンター


最新記事


最新コメント


最新トラックバック


月別アーカイブ


カテゴリ


DATE: CATEGORY:スポンサー広告
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
自作地形01
自作地形モデル
2枚の画像から地形を自動生成する機能を目指している。形は再現できたようだが、テクスチャが乱れている。



◎地形の作成

サンプルのモデル作成アルゴリズムと、ソーサリーフォースのtipsを参考にプログラムしたら、冒頭の画面になりました。
(コードは自作です)

このままだとテクスチャの乱れ方がわかりにくいので、デバッグ用に適当に文字を描いた画像と差し替えてみました。

自作地形02

文字をよく見ると、等間隔に細い横線が入ってますね。

テクスチャ座標の設定ミスじゃないか?と思ったのですが、テクスチャ座標の算出式は縦横同じです。なぜ横線のみ?



◎原因判明

横線の謎にハマッて半日ほど唸っていましたが、マップ上を飛行できる(カメラを自由に操作できる)ようにしたら、意外な事実が判明しました。
図解すると、こんな風になっていたのです。

断面図

テクスチャ座標の設定ミスではなくて、インデックスバッファの設定ミスでした。なるほど、縦線が無い理由も納得できました。

これって、カメラの角度を単発で変えただけじゃわからないものですね。カメラの角度を連続的に変化させることによって、初めて気付くことができました。
こ~ゆ~時は、マップ上の飛行テストが有効なんだなぁ。
1つ教訓になりました。



◎ミスの経緯

あまり参考にならないかもしれませんが、一応ミスの経緯を説明しておきます。

話はHeightmapCollisionのグレースケール画像にさかのぼります。この画像の解像度は2のn乗プラス1ですが、プラス1には理由がありました。

自分で頂点を配置するようになって、ようやく気付いたのですが、256×256のマス目のマップを作ろうと思ったら、257×257の頂点が必要です。257×257の頂点を準備するために、グレースケールの解像度も257×257必要だったのです。

しかし私のPCでは257×257だとエラーになるので、画像を256×256に修正すると、プログラムが誤動作します。サンプル実行時に黒い線が表示されるのは、このためです。

この状態で、GetHeight()で高さを取得可能なXZ座標範囲は、-3839~3809でした(TerrainScale=30の場合)。
30で割ると分かりますが、両端が1座標欠けています。

この対処がややこしくて適当にやっていたら、インデックスバッファの設定でさらに混乱して、ミスってしまいました。



◎インデックスバッファの修正

混乱を防ぐには、基本的な事から整理することが大切です。

グレーマップの画像解像度が256×256の場合
GetHeight()で取得可能な頂点数:254×254(最大)
頂点を最大数作成する場合、
・作成するポリゴン数:253×253×2
・作成するインデックス数:253×253

画像解像度が256×256の場合、インデックス数が253×253になることを理解できなくてミスったわけですが、最初から上記のように整理していれば、余計なミスは防止できたかもしれません。反省します。

…で、頭を整理して修正したらこうなりました。

自作地形03

おお、横線が綺麗に直りました!
でも、テクスチャの継ぎ目がまだちょっとおかしいですね。
惜しい!



◎次回予告

ここまで来ればあと一息!
次回いよいよクライマックス!?
(クライマックスって何?(^^;)

スポンサーサイト

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
<br/><a href="http://video.msn.com/video.aspx?vid=6d085a99-09a1-4288-a4ed-82e2e85ecc35" target="_new" title="XNA Creators Club Online: Particle 3D Sample">Video: XNA Creators Club Online: Particle 3D Sample</a>
Particle 3D Sample
XNA CREATORS CLUB ONLINEのサンプル実行画面。火や煙をパーティクルに表現している。



◎基礎勉強

コンテントパイプラインはあまり融通がきかないようなので、諦めてメインプログラム側で地形モデルを生成します。
とは言え、私はモデルをContent.Loadで読み込む方法しか知らないので、まず基礎から学ぶ必要があります。

そこで今回もソーサリーフォースのTips「プリミティブ(3D)」で一通り勉強させて頂きました。毎度ながら、ソーサリーフォースは初心者にも解りやすい丁寧な解説でありがたいですね。

これで頂点バッファインデックスバッファが使えるようになった(気がする)ので、地形モデルを作成しましょう。



◎バッファサイズは?

プログラムを書き始めると、すぐに素朴な疑問が生じました。
「バッファサイズは?」
マップデータを差し替え可能とする場合は、バッファサイズが変動します。そんな時はどうすれば良いのでしょうか?

「バッファぐらいとりあえず大きめに確保しとけばいーじゃん」と思っていたのですが、XNAのヘルプに「XNAでの動的頂点バッファ」という記述があったので読んでみると、意外に奥の深い話のようです。

この中でXNA CREATORS CLUB ONLINEのサンプルが3つも紹介されていたので、一通り目を通すことにしました。



◎PrimitivesSample

PrimitivesSample

プリミティブを扱ったシンプルなサンプルです。

頂点バッファを予め確保(デフォルトは500頂点分)し、そこに頂点を追加しています。空き領域がない場合、バッファ内容をレンダリングしてからバッファをリセットし、その後保留中の頂点を追加します。

この方式ならどのグラボでも問題なく動作しそうです。但し、バッファ容量の多いグラボでは、その効果は十分に発揮されないでしょう。
最初にスペックを確認してバッファ容量を最大限確保するのが理想と思いますが…そこまでする必要ってあるのかな?

このサンプルではPrimitiveBatchが実装されていて、これを取り込むとSpriteBatchと同様に使うことができそうです。地形もこれで作ろうかと考えましたが、インデックスバッファがサポートされていないのでやめました。



◎Particle 3D Sample

冒頭で紹介したサンプルです。

XNAユーザでまだ見たことがない人は、是非一度ダウンして実行してみてください。カメラ(視点)は自由に操作できますし、そうすることで立体感を味わうことができます。炎の中に突入することもできます。
(冒頭のビデオは何故カメラ固定なのか…勿体無いなぁ)
サンプルでここまで表現できるなんて凄いですね~。改めてXNAの実力を垣間見た気がします。


さて、プログラムに目を移すと、DynamicVertexBufferで動的頂点バッファを作成し、SetDataで頂点データを登録、更新しているようです。しかし頂点データの削除はどうやっているのか理解できませんでした。

プログラム全体を詳細に解析したい誘惑に駆られましたが、今回はDynamicVertexBufferを使わないので自制しました。
このサンプル、いずれ我が物にしちゃる!!



◎Generated Geometry Sample

GeneratedGeometry

ビットマップから地形と背景を生成するサンプルです。

地形生成はHeightmapCollisionと同じコンテントプロセッサが使われていました。こちらが先に作成されたようですね。
既にHeightmapCollisionを使っているので、これは参考にならないなぁ。でも、ゲームの背景としては参考になるかも。


本題とは関係ありませんが、360度のパノラマ画像をどうやって作成したのか気になって調べたら、こんな方法があるそうです。

「ビデオカメラの前に半球体の鏡を置いて、360度のパノラマ映像を1度に撮影し、再生の時には半球体の鏡を使って元に戻す」

360度パノラマ製作会社とか、デジカメ用360度レンズもありました。そういえば昔テレビで見たような…?



◎次回予告

結局、今すぐ参考になるサンプルはありませんでした。
でも近い将来別の所で役に立ちそうなので、心に留めておきます。

バッファサイズは「とりあえず大きめに確保し、一度作成して頂点数を確認してからプログラムを修正する」という行儀の悪い方法でやり過ごします。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
CLRデバッガ
CLRデバッガ
.NET Framework SDK v2.0付属デバッガ。コンテントパイプラインのデバッグに使用可能。紹介記事はこちら



◎色情報の取得

前回のエラーは、一度ソースを書き戻して再度修正したら出なくなりました。そんな訳で、結局何が悪かったのかよくわかりません。ごめんなさい。とりあえずハードの問題じゃなくて一安心。

結局、

 PixelBitmapContentでカラー情報を取得
 Vector4に変換してメインプログラムのContentTypeReaderに渡す
 Vector4からColor型に変換する

とすることでRGBA(赤、緑、青、透明)を取得しました。

最初は緑と青が常に0になるので悩みましたが、これは既存コードの影響で、色情報取得処理を先に行うと正常に取得出来るようになりました。



◎地形モデルの生成

カラーマップから地形種別を判別できるようになったので、今度は地形種別によって頂点位置を修正した地形モデルを作成したいのですが、ここでまた壁が立ち塞がりました。

地形モデルの生成コードは、サンプルからメインプログラムに丸ごとコピーしようと考えていたのですが、サンプルのコードはどうやらコンテントパイプライン専用らしいのです。
(肝心のMeshBuilderがカスタムインポータ用で、名前空間を追加して無理矢理移植しようとしてもダメでした)

そうなると、別途モデル生成サンプルを探して流用するか、別の方法を考える必要があります。



◎コンテントパイプラインへのデータ渡し

そもそも、カラーマップを読み込む際に、高さ情報を渡すことができれば、少しの改造で済むのですが…コンテントパイプラインにデータを渡すことは可能なのでしょうか?

A案:独自インポータを開発して、引数を追加する
B案:プロパティで受け渡す
C案:一旦ファイルに落として受け渡す

C案だと実行時に遅くなるし、XNAはファイルの扱いが面倒です。できればA案B案にしたいと思っていろいろ試行錯誤したのですが、どうにも上手くいきません。

やがてふと「コンテントパイプラインの処理は、ゲーム実行時ではなくビルド時に行われる」という記述を目にしました。
そうか~コンテントパイプラインって、XNBファイルを生成するだけの存在だったのね。
あれ?ということは、A案B案のようなメモリ連携は最初から不可能ってこと!?



◎コンテントパイプラインから別のコンテントを呼び出す

コンテントパイプラインの処理がビルド時に行われるなら、C案でも実行時に遅くなる心配はありません。しかし、C案はコンテントパイプラインの中から別のコンテントパイプラインを呼び出す必要があります。
これって可能なのでしょうか?

…結論から言うと、ダメでした。

Content.Loadを使用可能とするにはContentManagerのインスタンスを作成する必要がありますが、通常その引数にGameクラスのServicesプロパティを使用します。しかし今回はコンテントパイプラインの中なので、別途自力でサービスプロバイダを用意する必要があります。

さすがにこれは難しくて悩んでいたら、自分自身をgameクラスとして返却するコードを発見しました(こちらの後半のじぇいじぇいさんの回答)。

この「Gameクラス側のコード」を拝借して、コンテントパイプラインの中で強引にContentManagerを作成する所までは出来たのですが、Content.Loadを使用すると「~.XNBファイルが見つかりません」とエラーになりました。なるほど、ターゲットファイルは.XNB化された状態でないとダメなんですね。

それならばと、.XNBファイルを置いて実行したら「~.XNBの一部が見つかりません」とエラーになりました。
一部って何だよ~!



◎次回予告

あとちょっとで何とかなりそうなんですが…世の中甘くないですね。もう少し探ってみて、ダメならメインプログラム側で地形モデルを生成します。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
GPUの性能比較
Mizushima Network Service「GPUの性能比較」
自宅サーバー開設指南サイトだが、GPUの性能比較スコアを独自に付けたコーナーがある。グラボ購入時の参考に。



◎前回の続き

川を再現する方法として、C案で取り組むことにしました。B案はあまり応用がきかなさそうだし、D案は技術的に難しそうなので…。

では、C案について改めて説明します。

 グレースケールマップを読み込んで高さを取得する
 カラーマップを読み込んで地形の種類を取得する
 地形の高さと種類を元にして、地形モデルを生成する

については既に実装済みです。これを流用してを作成し、で新たな地形モデルを生成します。



◎コンテントパイプラインを流用する

の機能はの機能を流用して作成しますが、の機能も同時に利用するので、重複する識別子は全て変更する必要があります(クラス名、名前空間、GetRuntimeTypeの返却値など)。


さらにコンテントパイプラインの参照設定を行い、画像を登録し、Content Processorを設定…という段階で問題が発生しました。

新しく作成したコンテントパイプラインが、Content Processorの選択肢に表示されなかったり、やっと選択できるようになって設定したら異常終了したり、選択肢がまた消えたり…。

ただでさえコンテントパイプラインは苦手なのに、エラーにならずに例外発生で異常終了するのは、かなり厄介なケースです。悪戦苦闘を強いられましたが、何とか正常な状態にすることができました。

かなり試行錯誤したのでどれが要因かはっきりしませんが、メインプログラム側のContentTypeReaderを最初から用意していなかったのが原因だと思います(多分)。


また、参照設定を追加してるのに「コンテントパイプラインが見付からない」とエラーになるので、これも結構ハマりましたが、プロジェクト設定の「アセンブリ名」と「既定の名前空間」を修正したら解消しました。



◎カラー情報の判別

コンテントパイプラインの壁を越えて、ようやくカラー情報が取得できるようになりましたが、ここでまたハマりました。このままだとカラー情報がfloat型で返って来るので、実際に何色だか人間にはよく分からないのです。

float型からColor型に変換する方法は無いかと探ってみましたが、見付かりません。せめてint型なら、ビット演算でRGB値を抜き出せると思うのですが…。

で、変換が出来ないなら、PixelBitmapContent<float>を別の型にしようと試してみたのですが…エラーになりました。

Unsupported bitmap conversion. System.Int32 is not a valid PixelBitmapContent type.

う~ん何ですかねこのエラーは?まさかハード的にサポートされてないとか??



◎グラボ増設?

まさかとは思いますが、変なエラーが出る度に「もしかしたらハードかも…」と疑うのはいい加減疲れてきたので、グラボを買おうと決意しました。

お店で適当なグラボを選択し、念のため店員に「これ、うちのPCで動きますか?」とPCのマニュアルを渡したら「電力が足りない」とのこと。ガーン!マジっすか~!

まだ何も増設してないのに、いきなり電力不足を指摘されるとは思いませんでした。スロット4つもあるのに…シクシク。
最近のCPUやGPUって、そこまで電力喰ってたのね。小さなPC買ったのが裏目に出たか…。



◎次回予告

とりあえず、ハードじゃないことを祈りつつ、エラーの原因を探ります。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
fog設定等変更後
三国志軍記開発中の画面
サンプルを参考に、fog設定やバックカラー等を手直しした。遠方の雰囲気が少し変わった。



◎アンケート

いつの間にか回答が増えてました。ありがとうございます。
どうやら開発関係の方が多そうなので、当分このまま開発中心に進めていきます。

おや?3Dテストプログラムの続編を期待されている方もいるのでしょうか?ありがとうございます。特に予定はしていませんが、機会があればまた作ってみたいですね。



◎技術資料

前回までの高さ取得シリーズの総括を兼ねて、ホームページに「立体地形モデルの作成と高さの取得」を掲載しました。HeightmapCollisionを丸ごと流用する手順をまとめた資料です。

ちょっと長めの記事ですが、この記事を参考にすれば、コードの中身がいまいち理解できない人でも、欲しい機能が使えるようになると思います。
何しろ筆者自身が理解しきれてませんので…(汗)

まぁエンジンの構造を知らない人でも車は運転できますし、先に使い方を覚えて慣れていけば、そのうち中身もわかるようになる…といいなぁ(^^;



◎川モデルの作成

地表モデルを自動生成する場合、川モデルだけメタセコイアで作ると細部が微妙にズレてしまいます。そこで川モデルも自動生成すべく、こんなグレースケールを用意しました。

NanyougunRiverGrayScale512

これは川と道の部分だけグレースケールを継承し、他の部分を真っ黒にしたものです。これで川と道だけ浮き出させたモデルを作成し、地表モデルと重ねるつもりです。
で、実際にやってみると…

トゲトゲマップ

ガーン!何ですかこの針の山は!?
何でこうトゲトゲしているのでしょうか?

グレースケールマップを拡大してよく見ると、川幅は2~3ピクセルぐらいの所が多く、このような細い線はうまく生成されないようです。
う~ん、どうしたものか…。



◎また考える

諦めて元に戻すのはまだ早そうなので、再度考えてみました。

A案:グレースケールの解像度を縦横5倍以上にする
   →サイズ不適切のため却下

B案:川以外の地形は、明度を落として継承する

C案:カラーマップを読み込んで色別に地形を生成する
   プログラムを作る

D案:1つの地形モデルに複数のテクスチャを貼るよう
   プログラムする

こうして見ると、D案が一番素直そうなんですが、技術的には一番難しそうです。B案やC案なら私でも出来そうですが、それって逃げたことになるのかな~?

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
HeightmapCollisionテクスチャ差し替え
HeightmapCollision画像差し替え
グレースケールマップと地表テクスチャを差し替えた画面。従来の画面とは大分印象が違う。


◎間違いでした!

前々回の記事で「サンプルがエラーになる原因は2のn乗の問題」と書きましたが、これは間違いでした。ごめんなさい。
新たに発覚した事実も加えて整理すると、

[HeightmapCollisionでの画像サイズ]
・257*257はエラーになる
・256*256はエラーにならない
・512*512はエラーになる
・255*255はエラーにならない

つまり、今回のエラー(This device does not support 32-bit indices.…)と2のn乗の問題は別モノで、正しくは「グラボのインデックスリスト機能が16bitだから」です。
お騒がせしてすみませんでした。



◎補足

誤解が無いよう補足しておくと、このエラーとは別に2のn乗の問題は実在します。

[通常のプログラムでの画像サイズ]
・256*256はビルドエラーにならない
・255*255はビルドエラーになる
・512*512はビルドエラーにならない
・511*511はビルドエラーになる

通常のプログラムとは、HeightmapCollisionのようなコンテンツパイプラインを使用せずに、単純にContent.Loadで読み込む方法です。
この場合2のn乗を守らないとビルドエラーになりますが、ビルドエラーと今回のエラーを混同してしまいました。



◎サンプルを組み込む前に

いきなり訂正から始まりましたが、そろそろ本題に入ります。

HeightmapCollisionは、グレースケール画像の色を取得して地形モデルと高さ配列を生成するサンプルプログラムです。
画像を差し替えると、地形や配列も画像に合わせて生成されるよう汎用的に設計されています。

しかし、今回はメインプログラムで既に地形を作成済なので、地形生成部を削って配列生成部のみメインプログラムに組み込むつもりでした。
「高さだけ取得できればいいや」と考えていたのです。



◎地表のテクスチャ

しかしHeightmapCollisionのテクスチャ差し替え画面(冒頭参照)を見て、いろいろ考えさせられました。

まず、地表にテクスチャを貼っただけで、従来の三国志軍記のマップ画面とまるで印象が変わること。以前はのっぺりして古臭い印象でしたが、この画面は繊細でリアルな印象を受けます。

私はマップ上に森や荒地等の地形を追加していけば徐々に綺麗になるだろうと思ってあまり気にしていませんでしたが、先に地表全体にテクスチャを貼った方が良さそうです。



◎川や道のテクスチャ

しかしその場合、川や道などのテクスチャはどうしたら良いのでしょうか?地表テクスチャは同じパターンをマップ全体に均等配置していますが、川や道は、マップ全体を1枚で覆うように配置しています。

A案:マップ全体を1枚で覆うように地表テクスチャを配置
   →画像が粗すぎて見た目が悪くなる

B案:川や道のテクスチャも均等配置
   →おかしな画面になる

C案:地表テクスチャの上に川や道のテクスチャを重ねる
   →完成状態を想像すると、地表だけ繊細なのに
    川や道はのっぺりして違和感がある

D案:地形モデルの上に川や道のモデルを作って重ねる
   →川や道のモデルに繊細なテクスチャを均等配置
    すると、地表と似た感じになる?

D案で想像通りの画面になるか分かりませんが、とにかく試してみましょう。



◎サンプル組み込み

とりあえず地形モデルごと差し替えることにしたので、サンプルをそのまま取り込みます。下手に削るより楽チンです。

…で、実際に取り込んで動かすと「ContentTypeReaderが見付からない」とエラーになりました。

何かの設定ミスだろうと思って設定周りを調べたのですが、どこを調べても異常無し。結局原因は「コンテンツパイプラインの一部を書き換える必要がある」でしたが、それに気付くのに丸1日かかってしまいました(^^;

というわけで、地形をモデルごと差し替えた画面です。

地形差し替え直後

あれ?期待してたほどではないような…?地表のパターンが露骨するぎるし、山は以前の方が色も形も良いですね~。
まぁ、それでも地表は今回の方が良さげなので、テクスチャやfog設定などあちこち手直ししてみましょう。



◎次回予告

お陰様でマップの高さは無事取得できるようになりました。高さ取得シリーズは今回で終わりにします。
(GetHeight()で複数の座標を指定したら異なる値が返ってきました)

今後は細部を手直しして、座標系を合わせて、川や道を復活させて、城の位置を修正して…やることが一気に増えました(笑)

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
HeightmapCollision起動直後
HeightmapCollision
筆者がサンプルを起動した直後の画面。謎の黒い線が表示されている。


サンプルHeightmapCollisionの解析が終わったので、今回は解析結果を中心に記述します。


◎サンプル解析(概要)

1.TerrainProcessor.cs内で、グレースケールマップの
  色情報を取得し高さを決定、地形メッシュを構築する。
2.HeightMapInfoContent.cs内でも同様に
  高さ情報を取得し、2次元配列に格納する。
3.HeightmapCollision.cs内で、プレイヤーの入力に
  基づいてボールとカメラを移動する。



◎サンプル解析(詳細)

TerrainProcessor.cs:
1.グレースケールマップをピクセル単位に変換する
2.ピクセル単位で色(高さ)情報を取得し、新規メッシュに
  頂点を追加する(前半のforループ)
3.新規メッシュのマテリアルを設定する
4.新規メッシュに頂点を追加する(後半のforループ)
5.作成した新規メッシュを返却値として設定する

HeightMapInfoContent.cs:
1.ピクセル単位で色(高さ)情報を取得し、
  2次元配列に格納する(コンストラクタ)
2.作成した2次元配列を
  メインプログラムに渡す([ContentTypeWriter])

HeightMapInfo.cs:
1.2次元配列の値を利用して、
  指定された座標の高さを返す(GetHeight)

HeightmapCollision.cs:
1.キーやパッドの入力からボールの新座標と高さを
  算出する(HandleInput)
2.ボールに連動してカメラを移動する(UpdateCamera)
3.地形とボールを表示する(DrawModel)



◎黒い線の正体は?

私がHeightmapCollisionを起動すると、黒い線が表示されていました(冒頭参照)。私はこの線に沿ってボールを動かすゲームかと思っていたのですが、プログラムを解析しても、そのようなコードは見当たりません。
ひょとして、黒い線が表示されるのは私だけ…?(^^;

もしそうだとしたら、画像を257*257から256*256に修正したことが原因でしょう。試しに、128*128に修正したら…黒い線が綺麗さっぱり消えました。

黒い線は偶然の産物だったんですね。
分岐した線がゲームっぽいから気付きませんでした(笑)



◎線形補完する理由は?

HeightMapInfo.csのGetHeight()は、2次元配列の値を単純に返すのではなく、隣接座標との間の高さも取得し線形補完した値を返しています。(MathHelper.Lerp)
これは何故?

試しに、線形補完をやめて配列の値を直接返すよう改造すると、ボールを動かす際に、カメラ移動が鋭角になりました。自転車で砂利身を走った時にガタガタ揺れるような感覚で、全然気持ちよくないです。

どうやら、移動元と移動先に高低差がある場合でも、滑らかになるよう補完していたようですね。ボールはマップ座標系よりも細かい単位で動くので、マップ座標の隙間を補完することによって、より精密な高さを算出しているのでしょう。

線形補完の考え方



◎XNAの画像フォーマットについて

XNAで2D座標上の色を取得するメソッドは、今の所GetPixelしか見付かっていません。しかもPixelBitmapContentクラスにのみ提供されており、使用頻度の高いTexture2Dクラスなどでは提供されていません。

これは多分、Texture2D内のイメージデータのフォーマットがピクセル単位ではないため、一度PixelBitmapContentクラスに変換しないと、ピクセル単位の色を取得することができないのでしょう。

今回のサンプルでは、コンテンツから読み込むイメージデータをTexture2DContentクラスに格納し、Texture2DContent.Mipmaps[0]で取り出しています。

これはこれで良いのですが、Texture2DからPixelBitmapContentに気軽に変換できないものでしょうか?

というわけで、しばらく試したのですが…ダメでした。出来ればホームページのネタにしたかったんですけど、諦めます。
何か方法はあると思います(自力でミップマップをセットするとか)が、素直にコンテントパイプラインを利用した方が早そうです。



◎次回予告

やっとサンプルの解析が終わったので、メインプログラムに組み込みます。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
HeightmapCollision
HeightmapCollision
地形の高さを取得するXNA公式サンプル。ボールを地表に沿って動かすことができる。


◎シリーズ化決定!

「高さを取得するだけ」ってことで、最初は軽く見てましたが、どうやら一筋縄ではいかなさそうです。
他のサイトやサンプルでも1つのテーマとして扱っているので、改めてシリーズ化することとし、過去記事のタイトルを付け直しました。

見ての通り試行錯誤でやってますので、最終的にどうなるかは自分でもわかりません(笑)



◎色情報取得方法の追求(前回B案)

前回記事で「GetPixcelメソッドを見つけたものの、使い方がよくわからない」と書きましたが、進展がありました。
後日HPにまとめるつもりなので、この場で技術詳細は書きませんが、

1.名前空間の指定とDLLの登録が必要
2.「BitmapContent」と「PixelBitmapContent」は別モノ

この2点に気付かずに長いことハマってました(^^;

ようやくGetPixelがインテリセンスに現われたので、これで一気にいけるかな?
…と思ったのも束の間、すぐに次の壁が立ち塞がりました。
PixelBitmapContentに画像データをセットする方法がよくわからないのです。う~む…。



◎サンプルのエラー原因判明(前回CD案)

一方、naroさんのコメントを拝見して、CD案はサンプル解析から進めることにしました。

最初の問題は、サンプルがエラーになる点ですが…原因が判明しました!

「HeightmapCollision」と「TankOnAHeightmap」の両サンプルには、terrain.bmpが付属しています。その解像度が257*257なので、256*256に変更したら動きました。

ガーン!これは私にはちょっとショックでした。



◎2のn乗の問題

画像ファイルの解像度は2のn乗でないと動かないことがあるので、それに合わせて作るものだと思ってました。
(確かDirectX関連の記事にそんなことが書かれてました)

そのために結構苦労したんですけど、公式サンプルでこの状態ということは、2のn乗を無視した作品も多いってこと?

まぁXNA開発者の大半はまともなグラボを装備してるだろうから、開発側は問題無いと思いますが、一般ユーザの大半は、グラボ増設してません。
2のn乗で統一すると少しはユーザが増えることになりますが、普通は気にしないものなのか!?
…以上が、私がショックを受けた理由です。

ちなみに、サンプルは2のn乗プラス1でした。プラス1に何か特別な意味があるのかな?
まさかケアレスミスってことは無いと思いますが…。

それと余談ですが、もう1つの「BillboardSample」は、Xファイル読み込み時に例のエラーになります。前例からして、多分ハードが原因でしょう。このサンプルは今回扱わないことにします。




[2009/1/16追記]
この記事には間違いがありました。訂正記事はこちら



◎サンプルの解析

2のn乗の是非はともかく、サンプルが動くようになったので、HeightmapCollisionの内容解析に移ります。

…おや?コンテンツパイプライン内でグレースケールマップを読み込み、GetPixelで色を取得してますね。こんな所でGetPixelにお目にかかれるとは思いませんでした(笑)

色取得に関する情報がなかなか見当たらなかったので、色取得方式は邪道なのかと思い始めてましたが、公式サンプルでやってるってことは、一般的な方式ってことですね。少し安心しました(^^)



◎次回予告

まだサンプル解析中ですが、長くなってきたので続きは次回にします。

ちなみに、もう1つのTankOnAHeightmapは、高さだけでなく地面の傾斜も取得できるので高機能なんですが、
「今回そこまで必要なのか?」という疑問があるので、解析に踏み込まないかもしれません。
(城を傾けて配置するわけじゃないので…ユニットは微妙ですけど)

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
PIXforWindows
PIX for Windows
DirectX SDK付属のデバッグツール。リソース状況の確認やシェーダーのデバッグが可能。


◎アンケート

回答が増えてました。ありがとうございます!
「内容薄くてもいいからこまめに更新」が多いのかな?
毎日は無理ですが、なるべく日を空けないよう頑張ります。
回答状況は今後も時々チェックするようにしますので、よろしくお願いします。


では、前回記事の続きです。


◎特定座標の色の取得

当たり判定方式がダメっぽいので、次に考えたのは、特定座標の色を取得して、その色で高さを特定する方法。当たり判定方式よりもシンプルで負荷が低そうです。

現在のマップは高さに応じて色分けされていますし、別途グレースケールを用意することもできます。
ちなみに、グレースケールとはこんな感じの白黒画像です。色が白いほど高い場所です。
南陽郡地域図バンプテクスチャ512×512


興味本位もあって、まず3D空間内の特定座標(ポリゴン頂点とは無関係の座標)、またはそれを表示した画面の特定座標の色を取得できるか調べてみましたが、これに関する情報は殆ど見つかりませんでした。

唯一見つけたのはPIXというデバッグツール(冒頭参照)で、選択したピクセルがどのようにレンダリングされているか確認できます。(紹介記事はこちら
デバッグツールとしてはかなり使えそうですが、プログラムから直接呼び出して利用することはできなさそうです。


次に2Dテクスチャの特定座標の色を取得する方法を調べてみましたが、こちらも案外情報が少なく、未だ不明です。とりあえずGetPixcelメソッドを見つけたものの、XNA上での使い方がよくわかりません。(C#上とは違う?)

色の取得程度のことが簡単に出来ないってのは、我ながら情けないです。昔はVRAM直接アクセスで単純だったんですが…。



◎一般的な方法は?

だんだん煮詰まってきたので「そもそも一般的にはどうやってるのか?」から調べ直したら、MSDNフォーラムで「Meshからの座標取得について」というQ&Aを見つけました。

この質問は私がやりたいことと一致しているのですが、質問者と回答者のレベルが高すぎて、私にはかなり難解な内容です。これを見る限り、XNAにMesh.Intersectが無いから苦労しなければならないようですが…愚痴を言っても始まらないので、対処法を1つ1つ解読しましょう。



◎対処法の解読

まず対処法のひとつめは、「ランタイム時に~」とあるので、メッシュからリアルタイムに情報を取得して当たり判定に利用する方式と推測しました。

IndexBufferやVertexBufferについては未調査ですが、1つ気になるのは、XNAの公式サンプルや質問者がわざわざ手間がかかるふたつめの方式を採用した点です。よく理解しないままこちらの方式を採用するには不安がありますね。


対処法のふたつめは、コンテントパイプラインでXファイルを読み込む時に、頂点データを全て取得出来るので、
A:頂点データをメモリに退避して当たり判定に利用する
B:頂点データを活用して当たり判定用メッシュを作成する
上記ABを可能とする方式と推測しました。

推測が正しいか否かはさておき、ふたつめの方式の場合、コンテントパイプライン内でのプログラミング必須です。これは私にとって結構高い壁と言えます。



◎サンプルプログラム

Q&Aだけではどうプログラムすべきか見当も付かないので、とりあえずXNA Creators Clubのサンプルを入手して動かそうとしたのですが、

う、動かない…

似たようなサンプル「BillboardSample」「HeightmapCollision」でそれぞれ試した所、3Dモデル読み込み時に「This device does not support 32-bit indices.…」とエラーになります。環境上の問題っぽいですが、シェーダバージョンは1.1だからクリアしてるはずだし…う~む。



◎今後どうする?

というわけで、どうも一筋縄ではいかない雰囲気です。
現時点での選択肢を列挙します。

A案:(不正確と承知の上で)元の標高データを解析する
B案:XNA上での色情報取得方法をさらに追及する
C案:Q&Aのひとつめの方式を追及する
D案:Q&Aのふたつめの方式を追及する
E案:XNA以外で色情報をテキスト化してXNAに渡す

実はE案なら簡単にできそうなんですけど…「それでいいのかオイ?」って突っ込みたくなりません?(^^;

初めからそれをしなかったのは、XNAでやることによってXNAの技術力を上げたかったからです。でもこの様子だと相当時間かかりそうだし、プログラム自体は全然進んでないので、そろそろ挫けちゃいそうです。



◎次回予告

もうしばらくB~D案を追求するつもりですが…あまり進展が無かったら、E案にしてしまうかもしれません。

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

| BLOG TOP |
DATE: CATEGORY:三国志軍記開発
スクリーン上の位置からモデルを選択
ソーサリーフォース「スクリーン上の位置からモデルを選択
昨年紹介した「3次元座標からスクリーンへの座標変換」と逆の座標変換をテーマとしたTipsで、当たり判定も行っている。


◎アンケート結果

やはり回答率低いですね…2~3人?予想通りなんですけど、ちょっと寂しいです。そんな中でもわざわざご回答頂いた方、ありがとうございました!

さすがにこの人数なら集計するまでもないでしょう。結果が知りたい人はもう一度動画を見てください。

一番気にしてたのは「去年と同じく開発中心のままでいいのか?」という点ですが、賛否それぞれ1票って微妙ですね。誰かもう1票投じてくれると傾くんですけど(笑)


では、とりあえず去年の続きから再開します。



◎城のY座標

昨年は城モデルの配置座標(XZ座標)がずれている所で終わりましたが、座標をすぐに修正しなかったのは、先に城を配置する高さ(Y座標)を特定したかったからです。
城の配置座標(XZ座標)は見た目で適当に修正するわけですが、XZ座標修正後にY座標を変更すると、またずれてしまいます。

地形モデルは元々標高データをベースに作成したので、標高データからY座標を算出するのが筋だと思います。
しかしメタセコイアでの地形モデル作成時に、ポリゴン数を減らす加工をしてしまったので、既に標高データと地形モデルは一致しません。別の方法を考えましょう。



◎当たり判定

城名称を表示する際に「スクリーン上の位置からモデルを選択」を併読し、「これで城の高さが特定できるんじゃないか?」と考えました。

このTipsは、スクリーン座標から3D空間座標に変換して3Dモデルの当たり判定を行う方法を紹介したもので、スクリーン手前から奥に線を延ばして、その線が3Dモデルと衝突するかチェックします。
衝突した場合は、開始点から衝突点までの距離が返るとのこと。

今回の地形は3Dモデルなので、空中から地面に対して線を延ばし、その線が地面と衝突する距離をチェックすれば、正確な地面の高さが特定できそうです。



◎当たり判定用のメッシュ

…で、実際にプログラムを組み込んでから気付いたのですが、当たり判定を行うためには、当たり判定用のメッシュが別途必要なんですね。3Dモデルのメッシュがそのまま当たり判定に使えると思ってました。

…で、当たり判定用のメッシュを用意するには、当たり判定の形状を特定する必要があります。つまり、地形モデルの正確な形状(座標)が判らないと、この方法は使えないということです。

…この方法もダメっぽいですね。別の方法を探りましょう。



◎次回予告

長くなりそうなので、今回はここまでとします。
続きはまた明日!

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

| BLOG TOP |
DATE: CATEGORY:雑記



あけましておめでとうございます。
今年もよろしくお願い致します。


◎新春特別企画

新年一発目なので、何かいつもとは違うことをやろうと思い、ニコニコ動画ブログアンケートを作ってみました。

なるべく答えやすいよう、質問は選択式としましたが、何でも思い付いたことを記入してください。今後のブログ作りの参考としたいので、ご協力をよろしくお願い致します。

尚、背景に深い意味はありません。真っ暗だと寂しいので踊ってもらっただけです。(笑)


◎作ってはみたものの

一般的には、アンケートの回答率ってあまり伸びないんですよね~。このブログのアクセス数は、1日平均20人ぐらいだから、1割とすると…2~3人?
ちょっと寂しいけど、ダイレクトに意見が届くので、やりがいはあると思いますよ!
というわけで、よろしくお願いしまーす!

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

| BLOG TOP |

copyright © ゲーム制作の舞台裏 all rights reserved.Powered by FC2ブログ
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。