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


log

2009.11.17 C++:カメラ視線に沿って移動(サンプルつき)

ミップマップの自動生成方法をネットで調べてみても、あまり
詳しくのっておらず、よく分からず終いだったので。。
(まぁ自動生成でなくとも手動生成が分かっているので別にいいのですが…。)
今回は少し嗜好を変えて、新しくモデルの移動命令を導入することにしました。

ちょっと前にO3Dを使っていたときに、カメラの視線方向に沿って
モデルを移動させる処理をやっていて。これは面白いなと
思ったので、C++でもさっそく自作で導入してみることにしました。

ちょうど日記にまとまる程度のコード量だったので、以下に
処理を記述してみることにします。

// カメラの視線ベクトルの角度CameraDirZを求める
float CameraDirZ = atan2f(
(CameraTarget.z - CameraPos.z),
(CameraTarget.x - CameraPos.x)
);
// カメラの視線ベクトルとアップベクトルに対して
// 垂直なベクトルの角度CameraDirXを求める
float CameraDirX = CameraDirZ - D3DX_PI/2;
// カメラ視線の角度を元に移動量を計算して座標値に増分
Pos.x += cosf( CameraDirX ) * directionX +
cosf( CameraDirZ ) * directionZ;
Pos.z += sinf( CameraDirX ) * directionX +
sinf( CameraDirZ ) * directionZ;

これだけです笑。
ちなみに変数の説明をすると、
・CameraPos,CameraTarget:カメラの座標と注視点の座標
・directionX:上/下キーが押されている場合+/-移動量が格納されている
・directionZ:右/左キーが押されている場合+/-移動量が格納されている
・Pos:モデルの座標
こんな感じです。CameraPos,CameraTargetは
E3Dを使っている人ならおそらくピンと来るだろうと思います。
directionX,ZはO3Dのチュートリアルサンプルそのままの使い方です笑。

ベクトルや行列を普段から使っているプログラマーさんにとっては
何でもない処理だろうと思いますが。僕みたいに今まで
ライブラリで楽してきたエセプログラマにとっては意外と
参考になるのではないかなと、そう思います。

簡単な処理なのでE3Dでももちろん導入可能だと思います。
最近E3Dから離れていたので、これで少しくらいお役に立てるといいな。

2009.11.15 C++:ミップマップことはじめ

ファイル 206-1.jpg

とりあえずモーション読み込みはある程度完成したので背景も
読み込ませてみたところ、テクスチャ解像度が大きすぎたせいで
カメラを動かすとテクスチャがノイズのようにちらついてしまったので
ミップマップを導入してみました。

とりあえずミップマップのバイアス値を-1にして試してみたところ…。
とりあえずテクスチャ解像度が下がったように見えたと思いきや。

な、なんだこりゃ!

明らかにテクスチャの表示がおかしいです。(画像参照)
実際の画像ファイルと照らし合わせてみたところ、どうやら
ただ単純に画像の左上4分の1だけ使用していることが判明。

うーん。とりあえず、バイアス値について調べてみよ。

2009.11.14 C++:スキンメッシュ読み込みまであと少し!

ファイル 205-1.jpg

ある程度きれいにモーションが読み込めるようになりました。
モーション読み込みに、ある程度も糞もあるかい!って云いたくなりますが笑。

とりあえず分かったことを以下にメモしてみます。

XファイルはAnimation Keyの中にフレーム(骨)のモーション量を
格納していて。Keyの種類は全部で4種類あり、
Key Typeが0だと回転、1だとスケール、2だと移動、
3だと行列をそれぞれ格納しているのですが。回転の要素が特別な値を
格納していたので、どう使用していいのか今まで全く分からなかったのです。

スケール・移動は要素数が3つ、行列は要素数が16なので
それぞれX,Y,Zと行列の中身を格納しているんだなというのが
分かったのですが。回転の要素数は、なんと"4つ"なのです。

3Dをやっている方ならピンと来るのだと思いますが、こいつはX,Y,Z値を
そのまま格納している訳ではなくて、4元数つまりクォータニオン
というものを格納しているらしいです。

クォータニオンについて今まで全く勉強してこなかったので、
それはもう悪戦苦闘することになりました。。

結論を先にいってしまうと、
回転のAnimation Key要素は、おそらく先頭から順番に
Quaternion.w、Quaternion.x~zの要素を格納しているようです。
そのクォータニオンをD3DXMatrixRotationQuaternionで行列に
変換してしまえば他と同じように行列で統一できます。


これでとりあえず回転の処理は完成しましたが、なんだか
頭の頂点が後ろに引っ張られてしまってます(画像参照)。
まぁ、これはDirectX標準ビュアーでもこうなっていたので
おそらく単なるウェイトの設定ミスだろうと思います。

後は背景はアニメーション頂点バッファを生成していない為、描画できて
いないので、アニメーション有り無しで描画処理を切り替えれば完成!

そういえば、いままでC++はHSPと比べて軽い軽いと謳ってましたが、
モーション処理を考慮に入れることをすっかり忘れておりました。。
(HSP+E3Dの作者・ユーザーさんごめんなさい。)

モーション処理を考慮にいれると描画毎に頂点バッファを書き換えて、
ビデオメモリにバッファを転送しなければならないので、
それなりに処理が重くなりそうです。

あらかじめアニメーション分の頂点バッファをビデオメモリに
格納するという手もありそうですが。。それだとモーション補間できないからなあ。
けど、噂ではベイグラントストーリーはモーションの指定フレームだけ
あらかじめ作成しておいたモデルに差し替えることで
処理速度とクオリティを向上させていたんだそうな。

なるほど、少しだけやってみる価値がありそうだ。

2009.11.14 C++:モーションって…何だ

最近は長いことモーション読み込みと格闘しているのですが、
どうも一向に解決しそうにない感じです…。

動かすことには成功し、手足の伸びも解消できたのですが、
手足がなぜかばらばらな方向に回転してしまいます。
行列の設定がおかしいんでしょうけど、よく分からないのです。

それになぜか体の後ろの頂点だけ後ろにぐにょーんと
引っ張られてるという問題も発覚しました。
はじめは単なるウェイト設定ミスかと思ってましたが、
モデルを変えてみても同じでした。。

オフセット行列てなんだ…。クオータニオンてなんだ。
もはや分からないことが分からない状態!!

2009.11.12 C++:モーションは、やはり難しい

最近はモーションの読み込み部分に取り掛かっているのですが。難しい。
とある本を片手に、とりあえず読み込み部分を作ってみたものの
モーションは動かないは、行列の使い方がおかしいのか
動きの大きい部分がぐにょーんと伸びているは。。

参ったなぁ。とりあえず今はモーションの基本から勉強し直してるのですが、
原因を見つけるまで時間がかかりそうです。


なので、今回は制作とあまり関係ない話でも。
…しようかなと思いましたが止めにしとこうと思います笑。

昔みたいにまた映画などの考察をしようかと思ったのですが
最近は考察をしようとすると、結論を急ぐあまり余計なことまで
頭の中でぐるぐると反芻してしまうのを感じます。

ものづくりする動機さえ大切にしていれば、それでいいなと思える今日この頃。

2009.11.06 C++:モーション読み込み、やるぞー

ファイル 202-1.jpg

なんとなく背景を読み込ませてみました。

背景とキャラの比率があっていないので、…すごい、巨人だ笑。
一応これで基本的な読み込みはO3Dとほぼ同じになりましたが、
C++の方はテクスチャサイズがO3Dより全然大きいにも関わらず、
今のところ処理落ちが全くないです!すごい。

さて、いよいよモーション読み込みです。僕にとっては
全くの未開の地なので、どうなるのか分かりませんが
とりあえず少しづつやっていこうと思います。

僕のサイトにはほとんど人がこないので、技術的な話とかは
ほとんどメモ程度にしかまとめてないんだけど。ひょっとしたら
モーション周りは今でも興味ある人が少しくらいいるかな。

ManagedDirectXやXNAがでる前まではスキンメッシュは
ゲームプログラミングの山の一つといわれてたそうですが。
今だと簡単に読み込めるらしいですからね。

じゃあ何でわざわざC++でやってるんだよ!っていわれそうですが。
何というか。僕にとってC++は高校時代に挫折した苦い経験があるので
昔の自分を乗り越えるって意味も込めていたりします。

最近になって思うんですよ。「ようやく高3の頃のみんなの
技術に追いついたかなぁ」って笑。

2009.11.06 C++:Xファイルのマテリアル実装の仕様について

ファイル 201-1.jpg

ようやくXファイルの自作読み込みでマテリアルが読み込めるようになりました。
ついさきほど表示できたんですが、表示できたときは
「キターー」と思いました。うれしいなぁ。

ちなみにXフォーマットにあまり詳しくない人のために、
たかだかマテリアルの読み込みになぜここまで手間取ったのか
少しばかり説明しようかと思います。

Xフォーマットはタグテンプレートと呼ばれる要素単位で
テキストで保存されていて、マテリアル情報はMaterialというタグに、
メッシュとマテリアルとの関連付け情報はMeshMaterialListという
タグに登録されているのですが。

問題なのが、こいつらの登録方法がエクスポートするソフトによって
仕様がいくつも存在してしまうんです。

例えばMaterialListの中に直接Materialを登録しているXファイルもあれば、
MaterialListの外にMaterialListを登録して、MaterialListの下に
マテリアルインデックスの順番通りのマテリアル名だけ
記述しているものもあったり。
さらにはマテリアル名を登録しているXファイルもあれば、
マテリアル名を登録していないものもあったり。
駄目押しに、マテリアルインデックスが0からはじまるXファイルもあれば、
1からはじまったり、インデックスの途中でまた0を
はさんだりするXファイルもあったり。

それらの仕様に対応するようにこちらでプログラムを組まなきゃいけない訳です。
正直、「仕様をひとつにまとめんかい!」と毒づきたくもなりました。

自作読み込みをする上では、面倒なことこの上ないです、Xファイル。
しかし、それもようやくクリアできたのでとりあえず一安心です。

2009.11.04 C++:脱・頂点爆発

ファイル 200-1.jpg

なんとかXファイルの自作読み込みで頂点爆発させずに
読み込ませることができました。

何が原因だったかと思えば、SetStreamSourceのサイズ指定の
部分で頂点の構造体ではなく頂点バッファを渡しておりました。馬鹿だな…。

ただ、如何せんマテリアルとテクスチャの読み込みはまだ
行っていないので、今のところ木造の彫刻みたいになってます笑。

それと自作読み込みを表示させてみて、自作読み込みの方がなぜか
標準読み込みよりも身長の半分だけ高く表示されることに気づきました。
ちなみに画像では自作読み込みのモデルの方がやたら大きくみえるのは
大きい訳ではなくて、実際には上&手前にいるからです。
画像だと、分かりにくいですね。

はじめは自作読み込み関数がおかしいのかと思いましたが。
…よくよく考えてみるとカメラターゲットはモデルの座標位置に
合わせているので、標準読み込み側のモデルの中心が
画面の中心に来ていることを考えると…。どうやら標準読み込みの方が
自動でモデル中心をローカル原点に吸着させているようです。

改めて思うけど、やっぱり自作読み込みが一番安心するなあ。

余談ですが。最近特に寒くなってきたので、毛布を羽織ながら
制作しております。なので、全然手が進まないっ!
まいったな。

2009.11.02 C++:頂点爆発!と。

ファイル 199-1.jpg

現在、Xファイルの自作読み込みと格闘中です。
むこうのアイツにいってやりたい、マテリアルとサブセットの
クラスをいちいち分けるんじゃない、と。

とりあえず途中までは読み込めたようなので、試しに
やっつけRender関数を組んでみたところ…。(画像参照)

おー、これがうわさの頂点爆発か(遠い目)。


そういえば、マテリアル読み込み部分を調べてるときに
気がついたのですが、どうも僕のXファイルのマテリアルには
先頭にxof_defaultなる見慣れないマテリアルが存在していました。

それでマテリアル数を調べてみると、なぜか一つだけ少ない値を
とっていて、試しにそのマテリアル定義の部分だけ消して
プログラムを実行してみると…。何事もなく動くという。

うーん。何なんだろ。ボーン用マテリアルかと思ったけど
Xファイルはボーンじゃなくてフレーム構造で動かしてるし。
LWのスケルゴンの成れの果てかと思ったけど、だとしたら
何でマテリアル数としてカウントされてないんだろ。

標準のXファイル読み込みはxof_defaultのマテリアルが
存在した場合は読み飛ばす処理をさせてるんだろか。

さらに、今回は別の問題も発見。
何と一度スタンバイモードにしてから元に戻すとXファイルで
読み込んだデータだけ表示されなくなってしまいました。

おそらくデバイスロストあたりの問題なんだろけど、デバイスロスト時の
関数も既に導入済みなので、よく分かりません。

デバイスロストはレンダリングループ毎だけにチェックさせてるのですが、
デバイスロストも定期点検が必要なんですかね。

2009.10.31 C++:入力はいりました

C++のプログラムにようやくキー入力操作が入りました。
やっぱり動かせると楽しいな。
それとプログラム終了時にキャラクターの座標をSave.txtに
保存できるようにしてみました。ファイルの読み書きというやつです。

といってもまだ読み込み関数を作ってないけどね。
Xファイルの自作読み込みに使用するトークン関数とか
そのまま使えそうなので利用しようかな。

そういえば、最近はちらほらWeb3Dのデバッグテストとして
ちらほら紹介して回ったりしてるんだけど、「動かせましたー」という
人がいまのところ一人もいないのです…。

むむ。自分が使ってみたPCは2台中2台使えたのに。
まぁ、いいか。O3Dは自分専用ということで笑。