日別アーカイブ: 2009年2月12日

Direct2D (6) Tessellate

FillMesh() はまだ成功していません。
Tessellate() で座標を取ってみました。

iFactory->CreateRectangleGeometry(
		D2D1::RectF( 0.0f, 0.0f, 10.0f, 10.0f ), &iRect );
DummySink	tsink;
iRect->Tessellate( NULL, &tsink );

まずはただの矩形から。
少々勘違いしていたのは、AddTriangles() はまとめて一度だけ呼ばれるのかと思ったら
1 Triangle 毎に何度も呼び出されること。
結果は次の通り。

t0= 10.000000 0.000000, 10.000000 10.000000,  0.000000 10.000000
t1=  0.000000 0.000000,  0.000000 10.000000, 10.000000  0.000000

頂点の並びが少々おかしい気がします。
それぞれ回転方向が逆になっているので、Strip を展開したような形でしょうか。

ID2D1RectangleGeometry ではなく Path で同様の形を作ってみます。

ID2D1GeometrySink*	isink;
iFactory->CreatePathGeometry( &iPath );
iPath->Open( &isink );
isink->BeginFigure( D2D1::Point2F( 0.0f, 0.0f ), D2D1_FIGURE_BEGIN_FILLED );
	isink->AddLine( D2D1::Point2F( 20.0f,  0.0f ) );
	isink->AddLine( D2D1::Point2F( 20.0f, 20.0f ) );
	isink->AddLine( D2D1::Point2F(  0.0f, 20.0f ) );
	isink->EndFigure( D2D1_FIGURE_END_CLOSED );
	isink->Close();
iPath->Tessellate( NULL, &tsink );

全く同じです。

t0= 20.000000 0.000000, 20.000000 20.000000,  0.000000 20.000000
t1=  0.000000 0.000000,  0.000000 20.000000, 20.000000  0.000000

パスの方向を逆にしても同じでした。

isink->BeginFigure( D2D1::Point2F( 0.0f, 0.0f ), D2D1_FIGURE_BEGIN_FILLED );
isink->AddLine( D2D1::Point2F(  0.0f, 20.0f ) );
isink->AddLine( D2D1::Point2F( 20.0f, 20.0f ) );
isink->AddLine( D2D1::Point2F( 20.0f,  0.0f ) );
isink->EndFigure( D2D1_FIGURE_END_CLOSED );

t0= 20.000000 0.000000, 20.000000 20.000000,  0.000000 20.000000
t1=  0.000000 0.000000,  0.000000 20.000000, 20.000000  0.000000

半径 10 の円の場合。

iFactory->CreateEllipseGeometry(
	D2D1::Ellipse( D2D1::Point2F( 0,0f, 0.0f ), 10.0f, 10.0f ), &iElli );
iElli->Tessellate( NULL, &tsink );

22個の Triangle に分割されています。ちなみに半径 30だと 30個。

t0= -2.015625 9.796875, 0.000000 10.000000, 2.015625 9.796875
t1= 3.890625 9.218750, 2.015625 9.796875, -2.015625 9.796875
t2= -3.890625 9.218750, -2.015625 9.796875, 3.890625 9.218750
t3= 7.062500 7.062500, 3.890625 9.218750, -3.890625 9.218750
t4= -7.062500 7.062500, -3.890625 9.218750, 7.062500 7.062500
t5= 9.218750 3.890625, 7.062500 7.062500, -7.062500 7.062500
t6= -9.218750 3.890625, -7.062500 7.062500, 9.218750 3.890625
t7= 9.796875 2.015625, 9.218750 3.890625, -9.218750 3.890625
t8= -9.796875 2.015625, -9.218750 3.890625, 9.796875 2.015625
t9= 10.000000 0.000000, 9.796875 2.015625, -9.796875 2.015625
t10= -10.000000 0.000000, -9.796875 2.015625, 10.000000 0.000000
t11= 9.796875 -2.015625, 10.000000 0.000000, -10.000000 0.000000
t12= -9.796875 -2.015625, -10.000000 0.000000, 9.796875 -2.015625
t13= 9.218750 -3.890625, 9.796875 -2.015625, -9.796875 -2.015625
t14= -9.218750 -3.890625, -9.796875 -2.015625, 9.218750 -3.890625
t15= 7.062500 -7.062500, 9.218750 -3.890625, -9.218750 -3.890625
t16= -7.062500 -7.062500, -9.218750 -3.890625, 7.062500 -7.062500
t17= 3.890625 -9.218750, 7.062500 -7.062500, -7.062500 -7.062500
t18= -3.890625 -9.218750, -7.062500 -7.062500, 3.890625 -9.218750
t19= 2.015625 -9.796875, 3.890625 -9.218750, -3.890625 -9.218750
t20= -2.015625 -9.796875, -3.890625 -9.218750, 2.015625 -9.796875
t21= 0.000000 -10.000000, -2.015625 -9.796875, 2.015625 -9.796875

円の中心に頂点がありません。水平方向にスライスされているので、やはり Strip に
展開されているのだと思われます。

分割数は Tessellate() 2番目のパラメータで指定出来ます。
  Tessellate( NULL, ここ, &tsink );
省略時は D2D1_DEFAULT_FLATTENING_TOLERANCE が渡されており、これは 0.25f です。

値を大きくすると、5.0 くらいで菱形の 4角形になります。
0.0f を与えると 3862個に分割されました。

# 5.0
t0= -10.000000 0.000000, 0.000000 10.000000, 10.000000 0.000000
t1=  0.000000 -10.000000, -10.000000 0.000000, 10.000000 0.000000

RenderTarget 作成時 D2D1_RENDER_TARGET_PROPERTIES dpiX/dpiY に 0 を与えると
デフォルトの 96dpi になります。
96dpi の時、長さは pixel 相当となり、dpi 値を増やすとピクセル密度が高くなります。
相対的に同じサイズの RenderTarget に描かれる図形は大きくなります。

dpi を考慮した実際に描画される大きさと、Tessellate() 2番目の数値によって
生成される Triangle の数が決められています。

関連エントリ
Direct2D (5) ID2D1Geometry を使う
Direct2D (4) Direct2D の描画
Direct2D (3) 互換性の検証と Vista で Direct2D
Direct2D その(2) インターフェース
Direct2D と Direct3D10.1 の下位互換