ページ 11

描画の回転について・・・

Posted: 2007年11月07日(水) 12:28
by C.P.P
こんにちは☆
こちらのサイトではいつもいつも丁寧に教えていただいており、大変助かっております!

また質問です。質問ばかりですいません・・・

現在、DrawBoxやDrawLineを用いて描いた画像を構造体として一まとめにしているんですが、その画像をマウスのダブルクリックによって回転さたい(一回ダブルクリックする度に90度右に回転)んですが何かいい方法はございませんでしょうか?

ご教授お願いいたしますm(v_v)m

Re:描画の回転について・・・

Posted: 2007年11月07日(水) 14:02
by keichan
その構造体に角度パラメータを持たせてあげて、ダブルクリックされたら90度分角度変更させてあげればいけそうな気がします。

Re:描画の回転について・・・

Posted: 2007年11月07日(水) 14:06
by 管理人
その「画像を」回転すると仰っていることから、それを画像として扱っていいのならキャプチャーして固定画像にしてやるという手っ取り早い方法もあります。

http://homepage2.nifty.com/natupaji/DxL ... html#R3N12

描画されている画像を写真に撮ったみたいに画像にすることができます。そうすれば後はいくらでも回転が簡単です。

そうではなくて、座標変換をしたいのでしたら、若干数学的な話になります。
・・といっても、90度というキリのいい数字でしたら中学生でも簡単にわかる計算です。
(もっと簡単な方法があったらごめんなさい)


3Dのプログラムを書くとき、よく線形代数を使って回転させるのですが
http://www.ceres.dti.ne.jp/~ykuroda/oya ... sic3d.html
この辺わかりやすいです。今回は2Dなので、その上の所だけでOKです。

もし線形代数がわかりにくければ、単に2つの式を書くだけでOKです。
移動先の座標をダッシュであらわすとこのようになると書いてありましたね。

x' = x * cosθ - y * sinθ
y' = x * sinθ + y * cosθ

別にこれは難しい式ではなく、たとえばsin90°は1で、cos90°は0ですから、90°回転するときはこの式は

x' = - y
y' = x

というめちゃくちゃ簡単な式になります。180°ならsinは0,cosは-1になるので、これまた簡単な式になります。

もし90°単位ではなく、微妙な角度で回転したいなら、θにあたる部分をラジアンで渡してやってください。
円周率は約3.14159265ですから、これをdefineで最初に

#define PI 3.14159265

とでもしておいて、1°なら

sin(2*PI/360)

350°なら

sin(2*PI * 350/360)

このようにかけます。この時注意しないといけないのは、int型とdouble型の概念です。
私たちは
2 * 6 / 3
でも
6 / 3 * 2
でも同じ計算結果になると知っています。しかし、プログラムの場合、そうはいかず、

sin(350/360 * 2*PI)

先にint型で計算して、double型に変換すると、350/360=0の時点で答えが変わってしまい、期待する結果になりません。
これはPIがdouble型であることから、PIが計算に加わった時点でdouble型にキャストされるからです。

え~どうでもいいことで長くなりましたが、ご参考までにm(_ _)m

Re:描画の回転について・・・

Posted: 2007年11月09日(金) 16:14
by C.P.P
遅くなりまして申し訳ございません;;
keichanさん、管理人さん返信ありがとうございます☆

大変丁寧な説明で、座標変換かなり理解できました!

そこで自身で座標変換をやってみようとプログラムを組んでいたんですが、私のプログラムでは描画する際、
DrawBox(x1,y1,x2,y2,Color_Flug,TRUE)やDrawLine(x1,y1,x2,y2,Color_Flug,TRUE)などというという書き方ではなく、
DrawBox
(
home->disp_pos.x+home->scale*1, home->disp_pos.y+home->scale*3,
home->disp_pos.x+home->scale*9, home->disp_pos.y+home->scale*11,
home->is_dragging? Yellow: White, TRUE
);
と、いった関数で、描画しています。(これは、以前こちらのサイトで教えていただいた、マウスによって画像を移動し、マウスホイールによって拡大縮小するためです。)

普通にDrawLine(x1,y1,x2,y2,Color_Flug,TRUE)で座標移動しようとするならば、

DrawLine(x1,y1,x2,y2,Color_Flug,TRUE);
で画像を描いた後に、

if(描画された画像の範囲内でダブルクリックする){
int x1' = - y1;
int y1' = x1;
int x2' = - y2;
int y2' = x2;

DrawLine(x1,y1,x2,y2,Color_Flug,TRUE) → 表示フラグをFALSE
DrawLine(x1',y1',x2',y2',Color_Flug,TRUE) → 表示フラグをTRUE
}

という感じでやればいいと考えているのですが、(間違ってたらすいません・・・m(X.X)m)

DrawBox
(
home->disp_pos.x+home->scale*1, home->disp_pos.y+home->scale*3,
home->disp_pos.x+home->scale*9, home->disp_pos.y+home->scale*11,
home->is_dragging? Yellow: White, TRUE
);
のような関数で描画したときに、この関数を座標変換するにはどうしたらよいのでしょうか??

説明下手でもうしわけございません・・・
ヒントやアドバイス、何でも助かりますのでよろしくお願いいたします☆

また、質問の意味、内容が理解できない場合、気軽に言ってください・・・
本当によろしくお願いいたします☆

Re:描画の回転について・・・

Posted: 2007年11月09日(金) 18:04
by C.P.P
申し訳ございません!
自己解決しました!(おそらくですけど・・・)

今回は、座標変換のやり方がなかなか難しかったので、
一回元の画像を消し、新しく90度回転した画像を書き出すといったプログラムを作成しました☆

プログラムとしては
/**********************************************************************************/
// 線描画
static void Line_Draw(const Line *line)
{
// 非表示ならスキップ
if(!line) return;
if(!line->is_display) return;


DrawLine
(
line->disp_pos.x+line->scale*2, line->disp_pos.y+line->scale*3,
line->disp_pos.x+line->scale*12, line->disp_pos.y+line->scale*3,
line->is_dragging? Yellow: White, TRUE
);
}

/****************************************************************************************/
/**********************************************************************************/

// 回転された線描画
static void Line2_Draw(const Line *line)
{
// 非表示ならスキップ
if(!line) return;
if(!line->is_display2) return;


DrawLine
(
line->disp_pos.x+line->scale*3, line->disp_pos.y+line->scale*2,
line->disp_pos.x+line->scale*3, line->disp_pos.y+line->scale*12,
line->is_dragging? Yellow: White, TRUE
);
}

/****************************************************************************************/

この2つの画像を描くプログラムを作成して、
WinMain関数で

//線情報更新・描画
Line_Update(&line,&mouseInfo);
Line_Draw(&line);
Line2_Draw(&line);

というように呼び出します!
呼び出す条件としては
//90度回転する
if(line->is_display)
{
if(IsClickMouseRight(mouseInfo)
&& mouseInfo->pos.x >= line->pos.x - SrangeX
&& mouseInfo->pos.x <= line->pos.x + SrangeX
&& mouseInfo->pos.y >= line->pos.y - SrangeY
&& mouseInfo->pos.y <= line->pos.y + SrangeY)
{
line->is_display = FALSE;

if(IsClickMouseRight(mouseInfo)
&& mouseInfo->pos.x >= line->pos.x - SrangeX
&& mouseInfo->pos.x <= line->pos.x + SrangeX
&& mouseInfo->pos.y >= line->pos.y - SrangeY
&& mouseInfo->pos.y <= line->pos.y + SrangeY)
{
line->is_display2 = TRUE;
}
}

を線情報更新のところに挿入し、右クリックをダブルクリックする事で、90度回転した画像が出てきます☆

ここまではなんとか順調だったんですが、この新しく出てきました画像(90度回転された画像)をマウスによって移動しようとした場合、うんともすんとも言わなくなってしまいました・・・

なにかいい方法はありませんでしょうか?
また、上記プログラム悪いところがありましたらご指摘ください・・・

まだまだ初心者すぎて、このサイトやみなさんにはお世話になってばかりです。
申し訳ございません・・・
よろしくお願いしますm(v_v)m

Re:描画の回転について・・・

Posted: 2007年11月09日(金) 23:11
by Justy
画像をマウスのダブルクリックによって回転さたい
 基本的には keichanさんの書かれているとおり、角度のパラメータを保持し、
イベントに応じて回転させるという処理の流れになります。

 ただ、回転の方法はこの場合数種類の方法があります。

1 座標変換~家を構成する全ての頂点を回転させた座標を計算して表示
-> 数が多くなってくると処理が重くなります。

2 GetDrawScreenGraphでキャプって家を部分だけをテクスチャにして回転
-> この関数はこの時点で描かれている絵をテクスチャにするものなので、
描いたときに既に背景があったりするとそれも含めてテクスチャ化されます。
 しかも描いたあと、消さないと回転前の画像が残ってしまいます。

3 テクスチャに家を描画
 空テクスチャを作って、そのテクスチャに対して家を描いて
そのテクスチャを回転して表示する。


 3番目が一番楽です。
 手順としては

1 レンダリング可能なテクスチャを MakeScreen()で作成。
2 描画先を SetDrawScreen()でそのテクスチャに変更する
3 家を描く。
4 描画先を元(DX_SCREEN_BACK)に戻す
5 2で作ったテクスチャを DrawRotaGraph()などで回転させて表示、

 となります。


 サンプルは2種類用意しました。
 drag_test3a.cppは従来の操作に加えて、マウス右を押しながらホイール回転で
画像が回転します。
 こちらは毎フレーム家のテクスチャを作り直しています。
 
 対してdrag_test3b.cppは最初にテクスチャを作ったら基本的に
そのままのテクスチャを使います(右+左クリックで作り直せます)。

 この違いはホイール回転による拡大縮小をしてみると
わかると思います。



うんともすんとも言わなくなってしまいました
 よくわかりませんが、あたり判定の座標と表示の座標がずれているのでは
ないでしょうか

ありがとうございました☆

Posted: 2007年11月12日(月) 19:14
by C.P.P
ありがとうございます☆大変丁寧なサンプルまでつけていただき、大変助かりました♪

おかげ様でやっと、マウスによる移動 → 画像の回転という念願の処理が実現できました☆

本当にありがとうございます(^w^)v

まだまだ私は初心者で、質問の仕方や説明など至らなかったにもかかわらず、丁寧に教えていただきました、管理人さん、Justyさん、keichanさん、また大勢の方々、本当にありがとうございました☆

また、分からなかったら教えてください☆
お願いいたします☆