こんにちは.
1つ質問させて下さい.
楕円を回転させて描画したいのですが,
DXライブラリを用いた場合どうすれば良いでしょうか?
楕円を回転させた状態というのは,
楕円の短軸,長軸がX軸,Y軸と平行でない状態のことを言ってます.
ちなみに2次元の話で大丈夫です.
よろしくお願い致します.
DXライブラリ,楕円を回転して描画
Re: DXライブラリ,楕円を回転して描画
少なくとも、シェーダーを使えば可能なようです。
main.cpp
circle.fx
circle.fxはピクセルシェーダーとしてコンパイルし、
circle.psoというファイル名でexeファイルのカレントディレクトリに保存してください。
プロジェクト(ソースコードを含む)とバイナリ一式を添付します。
main.cpp
#include <DxLib.h>
#include <cmath>
char Key[256];
/*
(cx,cy)を中心にangle==0の時のx方向の半径rx、y方向の半径ryの楕円をcolorで描画する。
angleは右回り(時計回り)を正とし、ラジアンで表す。
*/
int DrawOval2(int cx,int cy,int rx,int ry,int color,float angle) {
float x1,y1,x2,y2,x3,y3,x4,y4;
float sine,cosine;
// 楕円が入る長方形の四隅の座標を計算する
if(rx<0)rx=-rx;
if(ry<0)ry=-ry;
sine=sin(angle);
cosine=cos(angle);
x3=cosine*rx-sine*ry;
y3=sine*rx+cosine*ry;
x2=cosine*rx-sine*(-ry);
y2=sine*rx+cosine*(-ry);
x1=-x3;y1=-y3;
x4=-x2;y4=-y2;
x1+=cx;y1+=cy;x2+=cx;y2+=cy;
x3+=cx;y3+=cy;x4+=cx;y4+=cy;
// シェーダーのパラメータを設定
static int shader=-1;
VERTEX2DSHADER vert[6]={};
FLOAT4 col;
int r,g,b;
vert[0].pos=VGet(x1,y1,0.0f);
vert[0].rhw=1.0f;
vert[0].u=0.0f;
vert[0].v=0.0f;
vert[1].pos=VGet(x2,y2,0.0f);
vert[1].rhw=1.0f;
vert[1].u=1.0f;
vert[1].v=0.0f;
vert[2].pos=VGet(x3,y3,0.0f);
vert[2].rhw=1.0f;
vert[2].u=1.0f;
vert[2].v=1.0f;
vert[3].pos=VGet(x1,y1,0.0f);
vert[3].rhw=1.0f;
vert[3].u=0.0f;
vert[3].v=0.0f;
vert[4].pos=VGet(x3,y3,0.0f);
vert[4].rhw=1.0f;
vert[4].u=1.0f;
vert[4].v=1.0f;
vert[5].pos=VGet(x4,y4,0.0f);
vert[5].rhw=1.0f;
vert[5].u=0.0f;
vert[5].v=1.0f;
GetColor2(color,&r,&g,&b);
if(shader==-1)shader=LoadPixelShader("circle.pso");
SetUsePixelShader(shader);
col.x=r/255.0f;
col.y=g/255.0f;
col.z=b/255.0f;
SetPSConstF(10,col);
// 描画する
DrawPolygon2DToShader(vert,2);
// エラーチェックは省略
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //裏画面に設定
int clWhite=GetColor(255,255,255);
int cx=320,cy=240;
int angle=0;
int rx=100,ry=50;
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されていない
//ココに処理を書いていく
if(Key[KEY_INPUT_A] && rx-3>0)rx-=3;
if(Key[KEY_INPUT_Q])rx+=3;
if(Key[KEY_INPUT_S] && ry-3>0)ry-=3;
if(Key[KEY_INPUT_W])ry+=3;
if(Key[KEY_INPUT_D])angle-=3;
if(Key[KEY_INPUT_E])angle+=3;
if(angle<0)angle+=360;
if(angle>=360)angle-=360;
DrawOval2(cx,cy,rx,ry,GetColor(0,255,0),angle*DX_PI_F/180.0f);
DrawString(10,10, " ↓ ↑",clWhite);
DrawFormatString(10, 40,clWhite," rx %5d A Q",rx);
DrawFormatString(10, 70,clWhite," ry %5d S W",ry);
DrawFormatString(10,100,clWhite,"angle %5d D E",angle);
ScreenFlip();//裏画面を表画面に反映
}
DxLib_End();
return 0;
}struct PS_INPUT {
float4 DiffuseColor : COLOR0;
float4 SpecularColor : COLOR1;
float2 TextureCoord0 : TEXCOORD0;
float2 TextureCoord1 : TEXCOORD1;
};
struct PS_OUTPUT {
float4 Output : COLOR0;
};
float4 color : register(c10);
sampler DiffuseMapTexture : register(s0);
PS_OUTPUT main(PS_INPUT PSInput) {
PS_OUTPUT PSOutput;
PSOutput.Output.r=color.r;
PSOutput.Output.g=color.g;
PSOutput.Output.b=color.b;
// 円を描画
if((PSInput.TextureCoord0.x-0.5f)*(PSInput.TextureCoord0.x-0.5f)+
(PSInput.TextureCoord0.y-0.5f)*(PSInput.TextureCoord0.y-0.5f)<=0.25f) {
PSOutput.Output.a=1.0f;
} else {
PSOutput.Output.a=0.0f;
}
return PSOutput;
}
circle.psoというファイル名でexeファイルのカレントディレクトリに保存してください。
プロジェクト(ソースコードを含む)とバイナリ一式を添付します。
- 添付ファイル
-
- shader_daen.zip
- 回転した楕円を描画するテスト
- (1.58 MiB) ダウンロード数: 157 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
-
田中
Re: DXライブラリ,楕円を回転して描画
みけCAT先生
本当にありがとうございます.
私の作成しているプログラムにも組み込むことが出来そうです.
ちなみになんですけど,
楕円を線だけで表示することは出来ますでしょうか??
(現在塗りつぶしになっているのですが,可能でしたら線で表示したいです.線の太さも指定できると最高です(> <)
本当にありがとうございます.
私の作成しているプログラムにも組み込むことが出来そうです.
ちなみになんですけど,
楕円を線だけで表示することは出来ますでしょうか??
(現在塗りつぶしになっているのですが,可能でしたら線で表示したいです.線の太さも指定できると最高です(> <)
Re: DXライブラリ,楕円を回転して描画
線だけでしたら、細かく分割して描画するのがいいと思います。
線の太さはとりあえず標準機能を使用してみましたが、今のところうまくいっていないようです。
#include <DxLib.h>
#include <cmath>
char Key[256];
/*
(cx,cy)を中心にangle==0の時のx方向の半径rx、y方向の半径ryの楕円をcolorで描画する。
angleは右回り(時計回り)を正とし、ラジアンで表す。
*/
int DrawOval2(int cx,int cy,int rx,int ry,int color,float angle,int thickness=1) {
float sine,cosine;
const int BUNKATU=512;
float px,py;
sine=sin(angle);
cosine=cos(angle);
px=cosine*rx;py=sine*rx;
if(rx<0)rx=-rx;
if(ry<0)ry=-ry;
for(int i=1;i<=BUNKATU;i++) {
float nowangle=i*2.0*DX_PI_F/BUNKATU;
float rawx,rawy;
float x,y;
rawx=rx*cos(nowangle);
rawy=ry*sin(nowangle);
x=cosine*rawx-sine*rawy;
y=sine*rawx+cosine*rawy;
DrawLine(cx+(int)px,cy+(int)py,cx+(int)x,cy+(int)y,color,thickness);
px=x;py=y;
}
// エラーチェック省略
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //裏画面に設定
int clWhite=GetColor(255,255,255);
int cx=320,cy=240;
int angle=0;
int rx=100,ry=50;
int thick=1;
while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されていない
//ココに処理を書いていく
if(Key[KEY_INPUT_A] && rx-3>0)rx-=3;
if(Key[KEY_INPUT_Q])rx+=3;
if(Key[KEY_INPUT_S] && ry-3>0)ry-=3;
if(Key[KEY_INPUT_W])ry+=3;
if(Key[KEY_INPUT_D])angle-=3;
if(Key[KEY_INPUT_E])angle+=3;
if(Key[KEY_INPUT_F] && thick>1)thick--;
if(Key[KEY_INPUT_R])thick++;
if(angle<0)angle+=360;
if(angle>=360)angle-=360;
DrawOval2(cx,cy,rx,ry,GetColor(0,255,0),angle*DX_PI_F/180.0f,thick);
DrawString(10,10, " ↓ ↑",clWhite);
DrawFormatString(10, 40,clWhite," rx %5d A Q",rx);
DrawFormatString(10, 70,clWhite," ry %5d S W",ry);
DrawFormatString(10,100,clWhite,"angle %5d D E",angle);
DrawFormatString(10,130,clWhite,"thick %5d F R",thick);
ScreenFlip();//裏画面を表画面に反映
}
DxLib_End();
return 0;
}複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)