ページ 11

矩形内に意図しないドットが表示される。

Posted: 2012年12月28日(金) 15:03
by taka
矩形内に意図しないドットが表示される。

剣の軌跡を表示するために DrawPrimitiveUPを使用して矩形を表示(アルファブレンド使用)するサンプルを作成
していたところ、矩形内に意図しないドットが表示されて困っています。
これといって特別なコードでないため、途方に暮れています。
問題点をご指摘ください。

コード:

#include <d3d9.h>
#include <d3dx9.h>

#define SAFE_RELEASE(p) {if(p){(p)->Release();(p)=NULL;}}

LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
D3DXVECTOR3 g_vEye(0.0f, 5.0f, -2.0f);
D3DXVECTOR3 g_vAt(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 g_vUp(0.0f, 1.0f, 0.0f);
float g_Aspect = 64.0f / 48;

struct CUSTOMVERTEX
{
	FLOAT x, y, z;
	DWORD color;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)

// 表示のポリゴン内に意図しないドットが表示される
CUSTOMVERTEX errorVtx[] =
{
	{ -1.747887f, 1.501374f, 0.123734f, 0x40FFFFFF},
	{ -1.229677f, 2.733887f, 0.803405f, 0x40FFFFFF},
	{ -1.741059f, 1.518516f, 0.132266f, 0x40FFFFFF},
	{ -1.146863f, 2.726068f, 0.793978f, 0x40FFFFFF},
	{ -1.733689f, 1.535205f, 0.140217f, 0x40FFFFFF},
	{ -1.066803f, 2.714993f, 0.783149f, 0x40FFFFFF},
	{ -1.726145f, 1.551732f, 0.145851f, 0x40FFFFFF},
	{ -0.988183f, 2.698073f, 0.770335f, 0x40FFFFFF},
};

// 表示に問題がない
CUSTOMVERTEX normalVtx[] =
{
	{  0.50f, 1.50f, 0.0f, 0x40FFFFFF},
	{  0.50f, 3.00f, 0.0f, 0x40FFFFFF},
	{ -0.50f, 1.50f, 0.0f, 0x40FFFFFF},
	{ -0.50f, 3.00f, 0.0f, 0x40FFFFFF},
};

HRESULT InitD3D( HWND hWnd )
{
	if(NULL==(g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))){return E_FAIL;}

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
    d3dpp.BackBufferCount = 1;
    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
    d3dpp.MultiSampleQuality = 0;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
	d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.Flags = 0;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

	if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))){
		if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))){
			return(E_FAIL);
		}
	}

	D3DXMATRIX matWorld, matView, matProj;
	D3DXMatrixIdentity(&matWorld);
	D3DXMatrixIdentity(&matView);
	D3DXMatrixIdentity(&matProj);
	D3DXMatrixLookAtLH(&matView, &g_vEye, &g_vAt, &g_vUp);
	D3DXMatrixPerspectiveFovLH(&matProj,
				D3DX_PI / 3.0f,
				g_Aspect,
				3.0f,
				15.0f);

	g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);
	g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
	g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);
    g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
	g_pd3dDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE );
    g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
    g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

	return S_OK;
}

VOID Cleanup()
{
	SAFE_RELEASE(g_pd3dDevice);
	SAFE_RELEASE(g_pD3D);
}

VOID Render()
{
	if(NULL==g_pd3dDevice) {return;}

	g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0, 0, 0, 0), 1.0f, 0 );

	if(SUCCEEDED(g_pd3dDevice->BeginScene())) {
		g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
		g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 6, &errorVtx[0], sizeof(CUSTOMVERTEX));
		g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, &normalVtx[0], sizeof(CUSTOMVERTEX));
		g_pd3dDevice->EndScene();
	}
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg ) {
		case WM_DESTROY:
			Cleanup();
			PostQuitMessage(0);
			return 0;
		case WM_PAINT:
			Render();
			return 0;
		case WM_SIZE:
			InvalidateRect(hWnd,NULL,true);
			return 0;
	}
    return DefWindowProc( hWnd, msg, wParam, lParam );
}

INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
	WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
						GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
						"Window1", NULL };
	RegisterClassEx( &wc );

	RECT rect;
	SetRect(&rect,0,0,640,480);
	AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
	rect.right=rect.right-rect.left;
	rect.bottom=rect.bottom-rect.top;
	rect.top=0;
	rect.left=0;

	HWND hWnd = CreateWindow( "Window1", "D3DPT_TRIANGLESTRIP sample",
						WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
						rect.right, rect.bottom, NULL, NULL, wc.hInstance, NULL );

	if(SUCCEEDED(InitD3D(hWnd))) {
		ShowWindow(hWnd,SW_SHOWDEFAULT);
		UpdateWindow(hWnd);
		MSG msg;
		while( GetMessage(&msg,NULL,0,0)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	UnregisterClass("Window1",wc.hInstance);
	return 0;
}

Re: 矩形内に意図しないドットが表示される。

Posted: 2012年12月28日(金) 23:15
by softya(ソフト屋)
ちゃんと座標を調べていませんが、以下の構造を守らていますか?
「トライアングル ストリップ (Direct3D 9)」
http://msdn.microsoft.com/ja-jp/library ... s.85).aspx

Re: 矩形内に意図しないドットが表示される。

Posted: 2012年12月29日(土) 03:42
by taka
softyaさん、返信ありがとうございます。
ご指摘くださったリンクを参照してみました。
問題提起をした座標は、トライアングル ストリップ の構造を守って生成したつもりの座標(実際にはボーンの
位置から計算で生成したもの)なのですが、
確認のつもりでこの座標情報が視覚的に正しいか確認するためにメタセコイアのファイルを作って見てみました。

Metasequoia Document
Format Text Ver 1.0

Scene {
pos 0.0000 0.0000 1500.0000
lookat 0.0000 0.0000 0.0000
head -0.5236
pich 0.5236
ortho 0
zoom2 3.1250
amb 0.250 0.250 0.250
}
Object "obj1" {
depth 0
folding 0
scale 1.000000 1.000000 1.000000
rotation 0.000000 0.000000 0.000000
translation 0.000000 0.000000 0.000000
visible 15
locking 0
shading 1
facet 59.5
color 0.898 0.498 0.698
color_type 0
vertex 8 {
-1.747887 1.501374 0.123734
-1.229677 2.733887 0.803405
-1.741059 1.518516 0.132266
-1.146863 2.726068 0.793978
-1.733689 1.535205 0.140217
-1.066803 2.714993 0.783149
-1.726145 1.551732 0.145851
-0.988183 2.698073 0.770335
}
face 3 {
4 V(0 1 3 2)
4 V(2 3 5 4)
4 V(4 5 7 6)
}
}
Eof

見てみた限り、トライアングル ストリップ の構造を守っていると思われるのですが?
指摘をされて、トライアングル ストリップ の構造を守っていないことが問題であるとすると、より単純な
D3DPT_TRIANGLELISTを用いて(先ほどの座標をリスト構造に変換したもので)表示をしてみたらどうなるかを
確認してみました。

コード:

CUSTOMVERTEX listVtx[] =
{
	{ -1.747887f, 1.501374f, 0.123734f, 0x40FFFFFF},
	{ -1.229677f, 2.733887f, 0.803405f, 0x40FFFFFF},
	{ -1.741059f, 1.518516f, 0.132266f, 0x40FFFFFF},
	{ -1.229677f, 2.733887f, 0.803405f, 0x40FFFFFF},
	{ -1.741059f, 1.518516f, 0.132266f, 0x40FFFFFF},
	{ -1.146863f, 2.726068f, 0.793978f, 0x40FFFFFF},
	{ -1.741059f, 1.518516f, 0.132266f, 0x40FFFFFF},
	{ -1.146863f, 2.726068f, 0.793978f, 0x40FFFFFF},
	{ -1.733689f, 1.535205f, 0.140217f, 0x40FFFFFF},
	{ -1.146863f, 2.726068f, 0.793978f, 0x40FFFFFF},
	{ -1.733689f, 1.535205f, 0.140217f, 0x40FFFFFF},
	{ -1.066803f, 2.714993f, 0.783149f, 0x40FFFFFF},
	{ -1.733689f, 1.535205f, 0.140217f, 0x40FFFFFF},
	{ -1.066803f, 2.714993f, 0.783149f, 0x40FFFFFF},
	{ -1.726145f, 1.551732f, 0.145851f, 0x40FFFFFF},
	{ -1.066803f, 2.714993f, 0.783149f, 0x40FFFFFF},
	{ -1.726145f, 1.551732f, 0.145851f, 0x40FFFFFF},
	{ -0.988183f, 2.698073f, 0.770335f, 0x40FFFFFF},
};


		g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 6, &listVtx[0], sizeof(CUSTOMVERTEX));
結果、D3DPT_TRIANGLESTRIPで表示した結果と変わりないようです。
なにか思い込みでひどい間違いをしているのか、上の考察も的が外れているのか。他にも検証すべき内容があ
りましたらご指摘ください。

Re: 矩形内に意図しないドットが表示される。

Posted: 2012年12月29日(土) 11:57
by softya(ソフト屋)
アルファブレンドしているんですね。
だとすると重なっている部分があるのかも知れません。

気になるのはfloat型の誤差でしょうか。

あとで、こちらでも実験してみます。

Re: 矩形内に意図しないドットが表示される。

Posted: 2012年12月29日(土) 12:53
by taka
softyaさん、返信ありがとうございます。
座標は、前に書きましたが、剣の軌跡を表示するためのデータで、扇のようなデータの意図しないドットが表
示される個所を取り出したものです。メタセコイアでも確認しましたが、扇の中心となる方の頂点がかなり接
近しています。
中心位置を外周寄りに変更のデータをメタセコイアで作成し、このデータを表示してみました。

{ -1.64f, 1.76f, 0.26f, 0x40FFFFFF},
{ -1.229677f, 2.733887f, 0.803405f, 0x40FFFFFF},
{ -1.63f, 1.75f, 0.26f, 0x40FFFFFF},
{ -1.146863f, 2.726068f, 0.793978f, 0x40FFFFFF},
{ -1.61f, 1.75f, 0.26f, 0x40FFFFFF},
{ -1.066803f, 2.714993f, 0.783149f, 0x40FFFFFF},
{ -1.60f, 1.75f, 0.25f, 0x40FFFFFF},
{ -0.988183f, 2.698073f, 0.770335f, 0x40FFFFFF},

g_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 6, &errorVtx1[0], sizeof(CUSTOMVERTEX));

結果は、意図しないドットは表示されなくなりました。
これは、float型の誤差と関係があるのでしょうか?
できれば、こうだからこうだ!という理由がはっきりわかるとうれしいのですが。
お気づきのことがありましたらご指摘ください。

Re: 矩形内に意図しないドットが表示される。

Posted: 2012年12月29日(土) 13:10
by softya(ソフト屋)
扇形なのでトライアングル ファンにしないと変な重なりが発生しますね。
http://msdn.microsoft.com/ja-jp/library ... 85%29.aspx
形状に応じて使わけてください。

Re: 矩形内に意図しないドットが表示される。

Posted: 2012年12月29日(土) 14:55
by taka
softyaさん、返信ありがとうございます。
"扇のような"と記述しましたが、剣の軌跡の頂点情報なので剣の根元、剣先の2頂点の軌跡を表示することを
目的としているのでD3DPT_TRIANGLEFANでは都合が悪く、D3DPT_TRIANGLESTRIPかD3DPT_TRIANGLELISTでの描画
を考えています。
softyaさんの"変な重なりが発生しますね"との記述より、剣の根元の頂点座標が近接しすぎなのが原因なので
しょうか?

Re: 矩形内に意図しないドットが表示される。

Posted: 2012年12月29日(土) 15:54
by softya(ソフト屋)
>剣の根元の頂点座標が近接しすぎなのが原因なのでしょうか?

私はそうだと思います。
エッジで重なりを発生しないための頂点パターンのバリエーションがD3DPT_TRIANGLEFANやらD3DPT_TRIANGLESTRIPやらですので頂点の順番は大変重要で、データを上手く作らないとエッジで重なりが発生します。

Re: 矩形内に意図しないドットが表示される。

Posted: 2012年12月29日(土) 16:46
by taka
>頂点の順番は大変重要で、データを上手く作らないとエッジで重なりが発生します。

データの構築からもう一度じっくり考えてみようと思います。
とりあえず、この質問について"済"にしようと思います。softyaさん、回答ありがとうございました。