DrawIndexedPrimitiveを用いて描画を試みています。
しかし、期待通りの表示になりません。
- real.png (33.5 KiB) 閲覧数: 3210 回
何が悪かったのでしょうか?
とりあえず、問題があると思われるソースコードを掲載します。
下の方に記述されているload関数とdraw関数をまずご覧ください。
あとはその関数内で呼ばれている関数等を追ってゆけばソースコードを解析できると思います。
► スポイラーを表示
static const DWORD LAND_FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
struct land_vertex
{
D3DVECTOR pos;
D3DVECTOR normal;
float u, v;
};
template<class T>
void saferelease(T * pointer)
{
if (pointer != nullptr)
{
pointer->Release();
pointer = nullptr;
}
}
bool init_vertex(
LPDIRECT3DDEVICE9 device, // in
int top_num_x, // in
int top_num_y, // in
int top_num, // in
int width, // in
int height, // in
int piece_num_x, // in
int piece_num_y, // in
IDirect3DVertexBuffer9 ** vertbuff) // out
{
HRESULT hr;
// 頂点情報格納バッファを作成
hr = device->CreateVertexBuffer(
sizeof(land_vertex)* top_num,
D3DUSAGE_WRITEONLY,
LAND_FVF,
D3DPOOL_MANAGED,
vertbuff,
NULL);
if (FAILED(hr)) return false;
// バッファをロックをして書き込みを開始する
land_vertex * pVtx = nullptr;
hr = (*vertbuff)->Lock(0, 0, fw::pointer_cast<void **>(&pVtx), 0);
if (FAILED(hr)) return false;
/*
* 1.最も左上の頂点情報から格納してゆく
* 2.左から右に向かって順々に頂点情報を格納してゆく
* 3.一番右まで格納し終えたら、一つ下の行に移動する
* 4.2→3を、最後の行になるまで繰り返す
*
*/
int target_index = 0;
for (int index_y = 0; index_y < top_num_y; ++index_y) // 上の行から下の行へ頂点情報を格納してゆく
{
for (int index_x = 0; index_x < top_num_x; ++index_x) // 左の列から右の列へ頂点情報を格納してゆく
{
land_vertex & vertex = pVtx[target_index];
vertex.pos.x = static_cast<float>(width*index_x) / piece_num_x;
vertex.pos.y = 0.0f;
vertex.pos.z = static_cast<float>(height*index_y) / piece_num_y;
vertex.normal.x = 0.0f;
vertex.normal.y = 1.0f;
vertex.normal.z = 0.0f;
vertex.u = static_cast<float>(index_x) / piece_num_x;
vertex.v = static_cast<float>(index_y) / piece_num_y;
++target_index;
}
}
// バッファをアンロックして書き込みを終了する
(*vertbuff)->Unlock();
return true;
}
bool init_index(
LPDIRECT3DDEVICE9 device, // in
int index_num, // in
IDirect3DIndexBuffer9 ** indexbuff, // out
int top_num_x, // in
int top_num_y, // in
int top_num, // in
int piece_num_x, // in
int piece_num_y) // in
{
HRESULT hr;
// 頂点インデックスバッファ作成
hr = device->CreateIndexBuffer(
sizeof(DWORD)* index_num,
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
indexbuff,
NULL);
if (FAILED(hr)) return false;
// バッファをロックして書き込み開始
DWORD * pIndex = nullptr;
hr = (*indexbuff)->Lock(0, 0, fw::pointer_cast<void **>(&pIndex), 0);
if (FAILED(hr)) return false;
/*
* N字状に頂点が取り出されるようにインデックスを設定してゆく
* 行の右端まで来たら、縮退ポリゴン用に同じインデックスをもう一個と、
* 次のインデックスをもう一個追加しておく。
* これを最後の行になるまで繰り返す。
* ただし最後の行だけは縮退ポリゴン用のインデックスを追加しない。
*
*/
int target_index = 0;
for (int index_y = 0; index_y < piece_num_y; ++index_y) // 上から下の行に向かってインデックスを格納
{
for (int index_x = 0; index_x < top_num_x; ++index_x) // 左から右の列に向かってインデックスを格納
{
pIndex[target_index] = top_num_x*(index_y + 1) + index_x; // まず下側のインデックスを格納
++target_index;
pIndex[target_index] = top_num_x*(index_y)+index_x; // 次に上側のインデックスを格納
++target_index;
}
// 縮退ポリゴン用のインデックスを追加する
const int piece_index_last = piece_num_y - 1; // 最後の行のindex_y
if (index_y < piece_index_last) // 最後の行よりも前の行だったら実行
{
pIndex[target_index] = top_num_x*(index_y)+top_num_x - 1; // この行の最後のインデックスと同じインデックスを追加
++target_index;
pIndex[target_index] = top_num_x*(index_y + 1 + 1) + 0; // 次の行の最初のインデックスと同じインデックスを追加
++target_index;
}
}
// バッファをアンロックして書き込み終了
(*indexbuff)->Unlock();
return true;
}
bool load(
LPDIRECT3DDEVICE9 device, // in
const TCHAR * path, // in
LPDIRECT3DTEXTURE9 * texture, // out
IDirect3DVertexBuffer9 ** vertbuff, // out
IDirect3DIndexBuffer9 ** indexbuff, // out
int * index_num, // out
int * triangle_num) // out
{
// 一つの三角ポリゴンの最大の大きさをここに定義する
// 三角ポリゴンの大きさがこれを超えないように、板ポリゴンはいくつかに分割されて管理される
const uint piece_size = 500;
saferelease(*texture);
saferelease(*vertbuff);
saferelease(*indexbuff);
HRESULT hr;
// テクスチャのサイズを調べて記憶する
D3DXIMAGE_INFO info;
hr = D3DXGetImageInfoFromFile(path, &info);
if (FAILED(hr)) return false;
int width = info.Width;
int height = info.Height;
int piece_num_x = width / piece_size + 1; // 板ポリゴンを格子状に分割管理したときの列数
int piece_num_y = height / piece_size + 1; // 板ポリゴンを格子状に分割管理したときの行数
int piece_num = piece_num_x * piece_num_y; // 板ポリゴンを格子状に分割管理したときの断片の個数
int top_num_x = piece_num_x + 1; // 板ポリゴンを格子状に分割管理したときの頂点の列数
int top_num_y = piece_num_y + 1; // 板ポリゴンを格子状に分割管理したときの頂点の行数
int top_num = top_num_x*top_num_y; // 板ポリゴンを格子状に分割管理したときの頂点の個数
const int top_per_row = 2 * top_num_x; // 一行につき何個の頂点情報を使用するか
const int top_of_grid = top_per_row * piece_num_y; // 格子状の頂点情報の合計
const int top_for_degen_per_row = 2; // 一行につき必要な縮退ポリゴン用の頂点情報の数
const int top_for_degen = top_for_degen_per_row * (piece_num_y - 1);// 縮退ポリゴン用の頂点情報の合計
*index_num = top_of_grid + top_for_degen; // 頂点インデックス情報の個数
*triangle_num = *index_num - 2; // 三角ポリゴンの合計
// テクスチャ作成
hr = D3DXCreateTextureFromFileEx(
device,
path,
D3DX_DEFAULT_NONPOW2,
D3DX_DEFAULT_NONPOW2,
0,
0,
D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
NULL,
NULL,
texture);
if (FAILED(hr)) return false;
bool result;
// 頂点バッファ作成、頂点データ設定
result = init_vertex(
device,
top_num_x,
top_num_y,
top_num,
width,
height,
piece_num_x,
piece_num_y,
vertbuff);
if (result == false) return false;
// 頂点インデックスバッファ作成、頂点インデックスデータ設定
result = init_index(
device,
*index_num,
indexbuff,
top_num_x,
top_num_y,
top_num,
piece_num_x,
piece_num_y);
if (result == false) return false;
return true;
}
bool draw(
LPDIRECT3DDEVICE9 device,
const D3DXMATRIX & world_mat,
LPDIRECT3DTEXTURE9 texture,
IDirect3DVertexBuffer9 * vertbuff,
IDirect3DIndexBuffer9 * indexbuff,
int index_num,
int triangle_num )
{
// ワールド変換行列設定
device->SetTransform(D3DTS_WORLD, &world_mat);
// 頂点フォーマット設定
device->SetFVF(LAND_FVF);
//マテリアル設定
static const D3DMATERIAL9 material = {
{ 1.0f, 1.0f, 1.0f, 1.0f }, // Diffuse
{ 0.1f, 0.1f, 0.1f, 0.1f }, // Ambient
{ 0.1f, 0.1f, 0.1f, 0.1f }, // Specular
{ 0.0f, 0.0f, 0.0f, 0.0f }, // Emissive
1.0f };
device->SetMaterial(&material);
//テクスチャ設定
device->SetTexture(0, texture);
device->SetStreamSource(0, vertbuff, 0, sizeof(land_vertex));
device->SetIndices(indexbuff);
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
//device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
//device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
//device->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT);
// プリミティブ描画
device->DrawIndexedPrimitive(
D3DPT_TRIANGLESTRIP,
0,
0,
index_num,
0,
triangle_num);
return true;
}
頂点情報の格納順は次図の通りです。
- top.png (6.18 KiB) 閲覧数: 3210 回
- index.png (9.08 KiB) 閲覧数: 3210 回
しかし、実際には設定したはずの頂点とはかけ離れた頂点が結ばれていくという結果になります。
ちなみにワールドマトリックスを単位行列にして実行したところ同じような結果になったため、ワールドマトリックスの指定が原因ではないようです。
何が間違っているのでしょうか?
よろしくお願いします。