11月5日(2008)


可変長引数を使った文字列表示関数の作成

今後絶対に使う便利機能として、やはり文字列表示は欠かせない、という事で、
printf()ライクな関数を作ることに。
引数に "..."を使うことで可変長の引数リストを渡せることは知りつつも、
printfっぽい実装は自分でやらなきゃならんのかと思っていたが、

vsprintf()

というタイムリーなタイミングで非常に便利な関数を知り解決。
sprintf()の可変長引数部分にva_listを渡せばいいだけ。

今回実装したプログラムは
void DxSys::SetString( int _x, int _y, const wchar_t *_str... )
{
   m_pSpriteFont->Begin( D3DX10_SPRITE_SAVE_STATE );
   {
      wchar_t str[32];
      RECT rect = { _x, _y, 0, 0 };   // 描画領域
       
       va_list argp;
      
      va_start( argp, _str );
      vswprintf_s( str, 32, _str, argp );
      
      m_pFont->DrawText(
               m_pSpriteFont,                       // 描画に使うスプライト
                  str,                                 // 文字列
                  -1,                                  // 文字数(NULL終端まで表示)
               &rect,                               // 描画領域
                  DT_LEFT | DT_NOCLIP,	                // 左揃え&クリップしない
                  D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f)); // 文字色(R=1.0f,G=1.0f, B=1.0f, A=1.0f)
   }
   m_pSpriteFont->End();
}

こんな感じです…。

ワイド文字、セキュリティ強化タイプの vswprintf_s()を使っています。
色々付き過ぎて段々とprintfの原型が薄れていってるような気がするが…。

va_startva_endがあるからって、必ずしも対にして使わなければいけないという
わけではないみたい。va_end は参照ポインタをNULLにリセットするだけっぽいので、va_listを
使い終わったらそのまま放置でも構わないっぽい。


ついでにデバッグ出力も…

↑の流れで、ついでにデバッグ用のprintf()的なものも作成。
基本は上記の流れと全く同じだが、最終的に文字列を流し込む関数に

OutputDebugString()

を使っている。


バインドした頂点バッファの解放

IASetvertexBuffers()によってバインドした頂点をRelease()しようとすると

D3D10: INFO: ID3D10Device::IASetVertexBuffers: A currently bound VertexBuffer is being deleted; so naturally, will no longer be bound. [ STATE_SETTING INFO #31: IASETVERTEXBUFFERS_UNBINDDELETINGOBJECT ]

というエラーメッセージが出力される。
出力されるからと言って、動作しないわけではないのだが、どうにも気持ち悪い。

今作ってるプロジェクトでは、毎フレーム、プリミティブデータを頂点バッファにコピー(初期化時のコピー)し使用しているので、使った頂点バッファは解放しないといけない。
実際、解放しないでタスクマネージャーを見たら使用メモリが増大していって恐ろしいことになった…。

フレームの頭で頂点バッファの解放、描画時に頂点バッファの確保、バインド、描画、という流れなのだが、
やはりバッファのリリースでこのエラーメッセージが出てしまう。

とりあえず現段階の回避方法としては、ダミーで作成した頂点バッファ(最初の初期化で一度だけ生成)を
解放前に割り当てるという方法だ。しかしまぁあまりスマートとは言えないよなぁ…。

IASetVertexBuffers()の使用バッファ数を0にしてみたが「とりあえずやめておけ」的な
エラーメッセージが出たのでやめる事に。やったところで解決しなかったし。

現時点で言えることは

アプリ生成時から終了まで破棄されない頂点バッファを作成しておき、
他の頂点バッファを解放するときはこのバッファを割り当てる

という事…。
まぁなんにせよ気持ち悪いな…。


プリミティブタイプの設定

プリミティブのタイプを設定する IASetPrimitiveTopology()
特にこの関数をコールしない初期の状態では D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED
セットされている模様。

この状態で

ID3DX10Sprite->Begin( D3DX10_SPRITE_SAVE_STATE )

とかでスプライト表示を行うと、環境復元時に内部で IASetPrimitiveTopology()がコールされ、
D3D10_PRIMITIE_TOPOLOGY_UNDEFINEDが再セットされて警告メッセージが出力されてしまう。

まぁ特に問題はなさそうだけど、最初の初期化で適当なプリミティブタイプを指定しておいたほうが良さそうだ…。
最終更新:2008年11月05日 19:45
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。