Re: 多角形の描画について ( No.1 ) |
- 名前:管理人 日時:2017/04/11 23:42
> C#にて画像を読み込ませ画像に多角形(多角形=三角形、四角形、五角形、六角形等)を描画したいのですが、色々な多角形を描画するにはどうすればいいのでしょうか?
三角形を描画するための関数 DrawTriangle や DrawTriangleAA がありますので、三角形は直接描画できます( DrawTriangleAA の方がアンチエイリアス付きなので綺麗です )
// 三角形を描画する( リファレンスページ https://dxlib.xsrv.jp/function/dxfunc_graph0.html#R2N7 )
int DrawTriangle( int x1, int y1, int x2, int y2, int x3, int y3, unsigned int Color, int FillFlag ) ;
// 三角形を描画する( アンチエイリアス付き )( リファレンスページ https://dxlib.xsrv.jp/function/dxfunc_graph0.html#R2N7_A )
int DrawTriangleAA( float x1, float y1, float x2, float y2, float x3, float y3, unsigned int Color, int FillFlag ) ;
ただ、四角形や五角形などの多角形を描画する機能はないので、DrawTriangle を何回も呼んで
多角形を描画する必要があります( 全ての多角形は三角形の集合で表現することができるのを利用します )
> また、多角形を塗り潰ししたり、
DrawTriangle の引数 FillFlag を TRUE( C# 版では DX.TRUE ) にすると中身が塗りつぶされます
> 背景との透過度を設定したりする事は可能でしょうか?
関数 SetDrawBlendMode を使用すると半透明にしたり加算半透明にしたり減算半透明にしたりすることができます
// 描画の際のブレンドモードをセットする( リファレンスページ https://dxlib.xsrv.jp/function/dxfunc_graph1.html#R3N17 )
int SetDrawBlendMode( int BlendMode , int Pal ) ;
例えば
SetDrawBlendMode( DX_BLENDMODE_ALPHA, 128 ) ;
を実行してから DrawTriangle を呼び出すと透明度50% で三角形が描画されます
よろしければお使いください m(_ _)m
|
Re: 多角形の描画について ( No.2 ) |
- 名前:らいよん 日時:2017/04/12 10:38
管理人様、いつも丁寧な説明ありがとうございます。
>ただ、四角形や五角形などの多角形を描画する機能はないので、DrawTriangle を何回も呼んで
>多角形を描画する必要があります( 全ての多角形は三角形の集合で表現することができるのを利用します )
もう少し教えて頂きたいのですが2D表示のみを行うとした場合、正四角形の場合はDrawFillBoxという関数が提供されているようなのでそちらを使っても
処理時間は同じぐらいなのでしょうか?後、塗り潰しと輪郭線の色を変えたい場合はDrawLine関数を使うのでしょうか?
それと例えばですが五角形を表示する場合で輪郭のラインと塗りつぶし色を変えたい場合の処理の流れは三角形関数を3回呼んで後に輪郭をDrawLine関数を5回呼んで
描画するのような流れという事でしょうか?
複数多角形を表示したいのですがその描画対象が三角形だったり、五角形だったりするのでpolygon関数、polyLine関数のような機能はありませんか?
※polygon関数、polyLine関数につきましてはもし実装されているのであれば教えて頂ければ幸いです。無いようでしたらC#の方でDrawTriangleAAとDrawLineを使って
polygon関数を作って使用させて頂こうと思います。
度々の質問で申し訳ありませんが宜しくお願いします。
|
Re: 多角形の描画について ( No.3 ) |
- 名前:管理人 日時:2017/04/13 00:13
> もう少し教えて頂きたいのですが2D表示のみを行うとした場合、正四角形の場合はDrawFillBoxという関数が提供されているようなのでそちらを使っても
> 処理時間は同じぐらいなのでしょうか?
正四角形でしたら DrawTriangle を2回呼ぶより DrawFillBox を呼んだほうが高速です
> 後、塗り潰しと輪郭線の色を変えたい場合はDrawLine関数を使うのでしょうか?
はい
> それと例えばですが五角形を表示する場合で輪郭のラインと塗りつぶし色を変えたい場合の処理の流れは三角形関数を3回呼んで後に輪郭をDrawLine関数を5回呼んで
> 描画するのような流れという事でしょうか?
はい、その通りです
ただ、DrawLine は座標が±1ドットずれることがあるので( Direct3D の仕様のためDXライブラリでは対処できない問題です orz )、
正確な輪郭を描画されたい場合は最初に『輪郭のラインの色』で DrawTriangle を使用して多角形を描画した後、
輪郭のラインの太さ分だけ小さくした多角形を『塗りつぶし色』で同じく DrawTriangle を使用して描画するということを
する必要があるかもしれません
> 複数多角形を表示したいのですがその描画対象が三角形だったり、五角形だったりするのでpolygon関数、polyLine関数のような機能はありませんか?
> ※polygon関数、polyLine関数につきましてはもし実装されているのであれば教えて頂ければ幸いです。無いようでしたらC#の方でDrawTriangleAAとDrawLineを使って
> polygon関数を作って使用させて頂こうと思います。
お手軽さは微塵もありませんが DrawPrimitiveIndexed2D という関数があります
// 2Dプリミティブを描画する(頂点インデックス使用)
// VERTEX2D *VertexArray : 描画に使用する頂点配列のアドレス
// int VertexNum : 頂点配列の要素数
// unsigned short *IndexArray : 描画に使用する頂点の番号を格納した unsigned short 配列のアドレス
// int IndexNum : unsigned short 配列の要素数
// int PrimitiveType : 描画するプリミティブのタイプ
// int GrHandle : 描画に使用するグラフィックハンドル
// int TransFlag : 透過処理を行うかどうかのフラグ( TRUE:透過処理を行う FALSE:透過処理を行わない )
int DrawPrimitiveIndexed2D( VERTEX2D *VertexArray, int VertexNum, unsigned short *IndexArray, int IndexNum, int PrimitiveType /* DX_PRIMTYPE_TRIANGLELIST 等 */, int GrHandle, int TransFlag ) ;
ラインを描画するかポリゴンを描画するかなどは PrimitiveType で指定します
// プリミティブタイプ
#define DX_PRIMTYPE_POINTLIST (1) // 点リスト
#define DX_PRIMTYPE_LINELIST (2) // ラインリスト
#define DX_PRIMTYPE_LINESTRIP (3) // ラインストリップ
#define DX_PRIMTYPE_TRIANGLELIST (4) // トライアングルリスト
#define DX_PRIMTYPE_TRIANGLESTRIP (5) // トライアングルストリップ
#define DX_PRIMTYPE_TRIANGLEFAN (6) // トライアングルファン
沢山種類がありますが、基本的にラインを描画する場合は DX_PRIMTYPE_LINELIST、
三角形を描画する場合は DX_PRIMTYPE_TRIANGLELIST を使用します
この関数を使用して毎フレーム 2000 個の6角形を DrawPrimitiveIndexed2D の呼び出し1回で描画する
プログラムを組んでみましたので、よろしければご覧ください
#include "DxLib.h"
// 描画する6角形の数
#define NUM 2000
// 頂点( 6角形1個あたり6個 )
VERTEX2D Vert[ NUM * 6 ] ;
// 頂点インデックス( 6角形1個当たり12個( 三角形4個なので 4 * 3 ) )
unsigned short Index[ NUM * 12 ] ;
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int i ;
int VertCount ;
int IndexCount ;
float PosX, PosY ;
// ウインドウモードで起動
ChangeWindowMode( TRUE );
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1;
// 描画先を裏画面に変更
SetDrawScreen( DX_SCREEN_BACK ) ;
// 頂点の変化しない要素はここで初期化
for( i = 0 ; i < NUM * 6 ; i ++ )
{
Vert[ i ].pos.z = 0.0f ;
Vert[ i ].rhw = 1.0f ;
Vert[ i ].u = 0.0f ;
Vert[ i ].v = 0.0f ;
}
// メインループ
while( ProcessMessage() == 0 )
{
// 画面をクリア
ClearDrawScreen() ;
// 描画する6角形の数だけ繰り返し
VertCount = 0 ;
IndexCount = 0 ;
for( i = 0 ; i < NUM ; i ++ )
{
// 描画する6角形の色を決定
COLOR_U8 Color = GetColorU8( GetRand( 200 ) + 55, GetRand( 200 ) + 55, GetRand( 200 ) + 55, 255 ) ;
// 描画する6角形の位置を決定
PosX = ( float )GetRand( 640 ) ;
PosY = ( float )GetRand( 480 ) ;
// 6角形の頂点の位置と色をセット
Vert[ VertCount + 0 ].pos.x = PosX - 8.0f ;
Vert[ VertCount + 0 ].pos.y = PosY ;
Vert[ VertCount + 0 ].dif = Color ;
Vert[ VertCount + 1 ].pos.x = PosX ;
Vert[ VertCount + 1 ].pos.y = PosY - 8.0f ;
Vert[ VertCount + 1 ].dif = Color ;
Vert[ VertCount + 2 ].pos.x = PosX + 8.0f ;
Vert[ VertCount + 2 ].pos.y = PosY - 8.0f ;
Vert[ VertCount + 2 ].dif = Color ;
Vert[ VertCount + 3 ].pos.x = PosX + 16.0f ;
Vert[ VertCount + 3 ].pos.y = PosY ;
Vert[ VertCount + 3 ].dif = Color ;
Vert[ VertCount + 4 ].pos.x = PosX + 8.0f ;
Vert[ VertCount + 4 ].pos.y = PosY + 8.0f ;
Vert[ VertCount + 4 ].dif = Color ;
Vert[ VertCount + 5 ].pos.x = PosX ;
Vert[ VertCount + 5 ].pos.y = PosY + 8.0f ;
Vert[ VertCount + 5 ].dif = Color ;
// 6角形を形成する3角形4個が使用する頂点の番号をセット
Index[ IndexCount + 0 ] = VertCount + 5 ;
Index[ IndexCount + 1 ] = VertCount + 0 ;
Index[ IndexCount + 2 ] = VertCount + 1 ;
Index[ IndexCount + 3 ] = VertCount + 5 ;
Index[ IndexCount + 4 ] = VertCount + 1 ;
Index[ IndexCount + 5 ] = VertCount + 4 ;
Index[ IndexCount + 6 ] = VertCount + 4 ;
Index[ IndexCount + 7 ] = VertCount + 1 ;
Index[ IndexCount + 8 ] = VertCount + 2 ;
Index[ IndexCount + 9 ] = VertCount + 4 ;
Index[ IndexCount + 10 ] = VertCount + 2 ;
Index[ IndexCount + 11 ] = VertCount + 3 ;
// 使用する頂点配列の要素番号を6進める
VertCount += 6 ;
// 使用するインデックス配列の要素番号を12進める
IndexCount += 12 ;
}
// 6角形をまとめて描画
DrawPrimitiveIndexed2D( Vert, NUM * 6, Index, NUM * 12, DX_PRIMTYPE_TRIANGLELIST, DX_NONE_GRAPH, TRUE ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// DXライブラリの後始末
DxLib_End();
// ソフトの終了
return 0;
}
6角形の頂点の位置や色を VERTEX2D 構造体の配列に代入して、各三角形を VERTEX2D 構造体の何番目の要素を
使用して描画するかを unsigned short の配列に代入して、最後に DrawPrimitiveIndexed2D で描画します
今回はただの図形描画と言うことでテクスチャは必要ないので引数 GrHandle には DX_NONE_GRAPH を指定しています
もしテクスチャを使用する場合は縦横のサイズが 2の乗数の画像を使用しないと正常に描画されませんのでご注意ください
あと、上記のサンプルでは 2000個の6角形を1回の DrawPrimitiveIndexed2D で描画していますが、
DrawPrimitiveIndexed2D の呼び出し1回は DrawTriangle や DrawFillBox の1回の呼び出しよりかなり重いので、
もし 2000個の6角形を 2000回の DrawPrimitiveIndexed2D の呼び出しで描画した場合は DrawTriangle を
8000回呼んで描画するよりも遅くなりますので注意してください
1回の描画でなるべく多くの図形を描画したほうが高速なのですが、頂点番号の指定に使用する変数の型が
unsigned short ( 保存できる値の範囲が 0 〜 65535 )なので、1度に描画できる3角形の数は最大でも
65535 / 3 = 21845個となります
ものすごい雑なご説明ですみません、不明な点がありましたらご質問ください m(_ _;m
|
Re: 多角形の描画について_解決 ( No.4 ) |
- 名前:らいよん 日時:2017/04/13 10:09
管理人様、ご丁寧な説明ありがとうございます。
その上、丁寧にサンプルソースまでご提示いただきありがとうございました。
提示いただきましたサンプルを参考に一度プログラムを作成して試してみたいと思います。
また不明な点が出たときには質問させて頂きますのでよろしくお願いします。
ありがとうございました。m(_ _)m
|
|