2013年09月19日

Direct3DとOpenGLで頂点宣言を共有したい

Android 向けと Windows 向けのプログラムを書いているので、グラフィック関連のインターフェースはなるべく同じにしておいて、OpenGL と Direct3D のどちらを使っているのか意識しなくても大丈夫なようにしたかったのですが、なんせ OpenGL と Direct3D では流儀が異なるため、そのままではうまくいきません。

とはいえ、行列の Colmun major order と Row major order の違いは単に転置すればよいだけだし、右手系左手系なんかもスケーリング行列を挟むだけで違いは吸収できるし、楽勝じゃん!!とか思っていたのですが、ただひとつ、頂点の構造体をつくりたいときに、色設定が Direct3D では D3DCOLOR (32ビット符号無し整数)なのに対し、OpenGL が float*4 になっていることが悩みでした。

使い勝手を考えると、Direct3D 側で色設定が float*4 でできるようになるのが一番なのですが、D3DFVF 列挙にはそういった指定が見当たりません。


と思ってたら、D3DFVF なんて使わないで IDirect3DVertexDeclaration9 使えばよかっただけみたい…


そんなわけで、例えば頂点として

struct VERTEX {
 float x, y, z;
 float r, g, b, a;
 float u, v;
};

を使うなら、Direct3D 利用時には


void DrawTriangleStripDX(const VERTEX *vertexArray, int numVertices) {
 D3DVERTEXELEMENT9 elm[] = {
  {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
  {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
  {0, 28, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
  D3DDECL_END()
 };
 IDirect3DVertexDeclaration9 *decl;
 g_D3DDevice->CreateVertexDeclaration(elm, &decl);
 g_D3DDevice->SetVertexDeclaration(decl);
 decl->Release();
 g_D3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, numVertices-2, vertexArray, sizeof(VERTEX)));
}

みたいに呼び出せばいいし、OpenGL 使用時には

void DrawTriangleStripGL(const VERTEX *vertexArray, int numVertices) {
 glEnableClientState(GL_VERTEX_ARRAY);
 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 glEnableClientState(GL_COLOR_ARRAY);
 glVertexPointer (3, GL_FLOAT, sizoef(VERTEX), ((const BYTE*)vertexArray) + 0);
 glColorPointer (4, GL_FLOAT, sizoef(VERTEX), ((const BYTE*)vertexArray) + 12);
 glTexCoordPointer(2, GL_FLOAT, sizoef(VERTEX), ((const BYTE*)vertexArray) + 28);
 glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices);
}

のようにすれば、同じ形式の頂点を OpenGL でも Direct3D でも使うことができる…と。
なんかすごく遠回りした気分。
posted by JUNOSOFT at 12:13| Comment(0) | プログラミング

2013年09月06日

ファイル名が欲しい5

今回は、ソート機能を追加してみようと思います


■ソートメニューを追加
・フォームを選択した状態で、「ソート(&S)」メニューを追加する


■パスを昇順(A→Z)でソートする
 配列をソートするには Array.Sort を使います

・「ソート(&S)」にサブメニュー「昇順(A→Z)」を追加
・private void 昇順AZToolStripMenuItem_Click(object sender, EventArgs e) {} というメソッドが追加されるので、
 そこに以下のコードを追加
 
  string[] lines = (string[])textBox1.Lines.Clone();
  Array.Sort(lines);
  textBox1.Lines = lines;
 

■パスを降順(Z→A)でソートする
 昇順ソート同じですが、最後にリストを逆順にします
 
・「ソート(&S)」にサブメニュー「降順(Z→A)」を追加
・private void 昇順AZToolStripMenuItem_Click(object sender, EventArgs e) {} というメソッドが追加されるので、
 そこに以下のコードを追加

  string[] lines = (string[])textBox1.Lines.Clone();
  Array.Sort(lines);
  Array.Reverse(lines);
  textBox1.Lines = lines;


■パスを拡張子順でソートする
 単純比較できない場合のソートには、比較用クラスを用意します
 
・「ソート(&S)」にサブメニュー「拡張子 昇順(A→Z)」を追加
・private void 拡張子順ToolStripMenuItem_Click(object sender, EventArgs e) {} というメソッドが追加されるので、
 そこに以下のコードを追加

  string[] lines = (string[])textBox1.Lines.Clone();
  Array.Sort(lines, new ExtComp());
  textBox1.Lines = lines;

・このままでは比較クラス ExtComp が存在せずコンパイルできないので、適当な場所に ExtComp クラスの定義を追加

  private class ExtComp : System.Collections.IComparer {
   public int Compare(object x, object y) {
    string ext1 = System.IO.Path.GetExtension((string)x);
    string ext2 = System.IO.Path.GetExtension((string)y);
    return String.Compare(ext1, ext2);
   }
  }

これで実行すると、たしかに拡張子順にソートされることが確認できます
posted by JUNOSOFT at 00:56| Comment(0) | プログラミング

2013年09月01日

始点1ピクセルが描画されない

ちょっと小ネタ

四角形のアウトラインを描画するときに、ラインを4本引いて四角形にしているのですが、
左上の1ピクセルが常に欠けているのがすごく気になってました。
以下のコードでいうと、ドットバイドットで描画したときに (x0, y0) の1ピクセルが必ず欠けます。
直線描画のときだけ欠けるので、ステンシルマスクやZバッファの問題ではなさそうです。

struct VERTEX {
 float x, y, z;
};
const VERTEX v[] = {
 {x0, y0, 0},
 {x1, y0, 0},
 {x1, y1, 0},
 {x0, y1, 0},
 {x0, y0, 0}};
device->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE);
device->DrawPrimitiveUP(D3DPT_LINESTRIP, 4, v, sizeof(VERTEX));

終点の1ピクセルが描画されないのであれば D3DRS_LASTPIXEL が FALSE になっているのかな、とも思うのですが、
なぜか終点ではなく始点です。というか、仮に始点が描画されない設定になっているなら4本目の終点としての x0, y0 が、
終点が描画されない設定になっているなら、1、2本目の始点としての x0, y0 が、始点終点両方とも描画されない設定になっているなら、
x0, y0 だけでなく4頂点すべてが描画されないはずです。謎です。

どうも納得がいかないのですが、結局太さ1ピクセルの超細長い長方形ポリゴンを描画して直線の代わりにしました。
拡大したときに直線の太さが1ピクセルでなくなってしまいますが、ドットバイドットが基本のゲームなのでそこは問題無しとします。釈然としませんが…
posted by JUNOSOFT at 11:42| Comment(0) | プログラミング