合計 昨日 今日

DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: sereparu
[URL]
かけだし(2,351 ポイント)
Date: 2017年3月12日(日) 00:15
No: 1
(OFFLINE)

 DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

はじめまして。
VC++とDXライブラリを始めたばかりの初心者です。

DrawModiGraphで画像を三次元的に回転させる方法を考えているのですが、上手く行かず困っています。
どう上手く行かないのかは後述します。

以下の「DrawModiGraph関数を用いて画像を回転させたいのですが」というトピックで
DrawModiGraphで画像を平面方向に回転させる方法を見つけ、XYZ軸にも回転できるのでは、と考えました。
DrawModiGraphに拘っているのは、二次元の座標上に三次元的に回転する画像を表示させたいのと
画像の四つの頂点の座標を当たり判定に使用したいからです。

・「DrawModiGraph関数を用いて画像を回転させたいのですが」
viewtopic.php?f=3&t=9720

数学が苦手で回転の公式は理解が難しかったので、とりあえず上記トピックのコードを
色々と試行錯誤しながらXYZ軸に回転できるよう改造してみたものが以下のコードです。

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "DxLib.h"
#include <math.h>
 
// Π(パイ)
#define PI 3.1415926535897932384626433832795f
 
// 回転描画処理
extern void kaiten();
 
extern int size_x = 0; // 画像のxサイズ
extern int size_y = 0; // 画像のyサイズ
extern float x = 320;  // 画像の中心x座標
extern float y = 240;  // 画像の中心y座標
extern int rota_x = 0; // x軸回転角度
extern int rota_y = 0; // y軸回転角度
extern int rota_z = 0; // z軸回転角度
 
extern int graph = 0;  // グラフィックハンドル
 
// WinMain 関数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    //ウィンドウモードに変更
    ChangeWindowMode(TRUE) ;
   
    // DXライブラリ初期化処理 エラーが起きたら終了
    if(DxLib_Init() == -1) {
        return -1;
    }
 
    // 描画先を裏画面に設定
    SetDrawScreen(DX_SCREEN_BACK);
 
    // グラフィックハンドルの設定
    graph = LoadGraph("test.png");
    GetGraphSize(graph, &size_x, &size_y);
 
    while (0 == ProcessMessage() && 0 == ClearDrawScreen() &&
        0 == CheckHitKey(KEY_INPUT_ESCAPE)) {
 
        // 回転描画処理
        kaiten();
       
        // 回転角度加算
//        rota_x++;
//        rota_y++;
//        rota_z++;
 
        ScreenFlip();
    }
 
    DxLib_End(); // DXライブラリ使用の終了処理
    return 0;    // ソフトの終了
}
 
// 回転描画処理
void kaiten()
{
    // 回転後の座標
    int X = 0;
    int Y = 0;
 
    // 各回転角度をラジアンに変換
    double radi_x = rota_x * PI / 180.0;
    double radi_y = rota_y * PI / 180.0;
    double radi_z = rota_z * PI / 180.0;
 
    X = -(size_x / 2) * cos(radi_z + radi_y) - -(size_y / 2) * sin(-radi_z);
    Y = -(size_x / 2) * sin(-radi_z) + -(size_y / 2) * cos(radi_z + radi_x);
    int ax = x + X;
    int ay = y + Y;
 
    X = (size_x / 2) * cos(radi_z + radi_y) - -(size_y / 2) * sin(-radi_z);
    Y = (size_x / 2) * sin(-radi_z) + -(size_y / 2) * cos(radi_z + radi_x);
    int bx = x + X;
    int by = y + Y;
 
    X = (size_x / 2) * cos(radi_z + radi_y) - (size_y / 2) * sin(-radi_z);
    Y = (size_x / 2) * sin(-radi_z) + (size_y / 2) * cos(radi_z + radi_x);
    int cx = x + X;
    int cy = y + Y;
 
    X = -(size_x / 2) * cos(radi_z + radi_y) - (size_y / 2) * sin(-radi_z);
    Y = -(size_x / 2) * sin(-radi_z) + (size_y / 2) * cos(radi_z + radi_x);
    int dx = x + X;
    int dy = y + Y;
 
    // 描画
    DrawModiGraph(ax, ay, bx, by, cx, cy, dx, dy, graph, TRUE);
}


見よう見まねで作ったので、思い通りの動きが実現できません。
実現させたい動きを、メタセコイアという3DCG作成ツールで再現したアニメーションを作りました。

・三次元回転アニメーション
https://gifmagazine.net/post_images/1254897

アニメーションの①~③のように単一の軸で回転させたときの動きは実現できているのですが
④~⑦のように複数の軸で回転させたときの動きがアニメーションの動きと違ってしまいます。
どう違うのかは言葉で表現しづらいので、上記コードの46~48行目のコメントアウトを外して
実際に画像を回転させてみてご確認いただければと思います。

アニメーションのように複数の軸で回転させるにはどうすれば良いでしょうか?
出来れば上記コードを具体的に修正したものをご回答いただけると嬉しいです。

よろしくお願い致します。

・開発環境
 OS:Windows7(64bit)
 コンパイラ:VC++ 2008 ExpressEdition
 ライブラリ:DXライブラリVer3.17c

Name: Math
[URL]
Date: 2017年3月14日(火) 19:59
No: 2
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

残念だけれど”もともと2次元の画像”なので出来ないと思います。
X-Y軸の回転を合成すると2次元画像の”canvas”がズーム・ダウンー(逆転して)ズーム・アップを繰り返すだけです。
(雑談:メタセコイヤを入れました。MikuMikuDance を使っていますがMikuMikuDanceの開発終了が宣言されおりメタセコイヤを使って見ようと思います)

Name: sereparu
[URL]
かけだし(2,351 ポイント)
Date: 2017年3月14日(火) 22:25
No: 3
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

Mathさん
ご回答ありがとうございます。
やっぱり無理なんですね。別の方法を考えてみます。

Name: usao
[URL]
ハッカー(126,567 ポイント)
Date: 2017年3月15日(水) 13:44
No: 4
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

Offtopic :
DrawModiGraphというのが実際に何をしてくれるのか知らないけれども,
ググってリファレンスらしきものを見た感じの雰囲気では
アフィン変換を求めて描画してくれるものなのではないかと想像します.
訂正:3点ではなく4点与えるなら射影変換をサポートしている可能性がありますね.

リンク先のアニメーションが見れなかったので,何とも言えませんが,
描画すべき像の様子がDrawModiGraphでできる範疇に収まるのであれば,
4点の座標とやらを適切に自前で計算してそれを与えれば,どうにかなりそうにも見えますが,どうなんでしょう?
(欲しい絵が透視投影なものなら無理っぽい気がするけど,正射影的なものならいけるのでは?)

例えば,別の手段で作ったというアニメーションのあるフレームにおける4点の座標を
手動で(例えばスクリーンショットを撮って,ペイントか何かで4個の角の座標を調べるとかして)そのDrawModiGraph()という関数に与えてみて,
描画結果が望むものか否かを確認することはできないのでしょうか.
いくつかのパターンで試した結果が
・絵的に大丈夫そうであれば,後は4点の座標を求めるところだけの問題になる.
・絵的に既にダメそうなら,別の方法が必要かも.

Name: sereparu
[URL]
かけだし(2,351 ポイント)
Date: 2017年3月15日(水) 21:32
No: 5
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

usaoさん
ご回答ありがとうございます。

射影変換については、よく知らないので調べてみます。

アニメーションの4点の座標をDrawModiGraphの引数に与えると
絵的には望み通りの結果が得られるので、後は座標を求める計算だけを何とかすれば
実現できるのではないかと思っています。

Name: usao
[URL]
ハッカー(126,567 ポイント)
Date: 2017年3月16日(木) 09:49
No: 6
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

最終的に必要な一次変換(アフィン変換,射影変換)を求めてどうのというあたりについては
DrawModiGraphなる関数が勝手に解決してよろしくやってくれる(と思われる)ということなので,
必要なのは4点の変換後の座標を求むことですね.

自前で計算する際のざっくりとしたイメージは以下のような感じでしょうか.

(1)元の画像は2次元だけど,これを,仮想的に3次元空間上での「四角い平板」だと考えます.
 W*H[pixel]の画像が,仮想3次元空間上でどれだけのサイズを有するのかは「自分に都合がいいように(考えやすいように)」決めます.
 (例えば,W*H[空間上謎単位]とか.)

(2)3次元空間の中に,(1)の平板と,仮想的なデジカメを配置して,仮想的な撮影を行います.(=平板の4つ角が,仮想撮影結果画像のどこに移るのかを計算する)
 平板がカメラの視野に入っていれば写ります.平板の写り方はカメラの配置と平板の配置の関係次第となります.
 ・カメラをわかりやすい位置に配置しておいて,平板の方の位置と姿勢を決める のでも
 ・平板をわかりやすい位置に配しておいて,カメラの方の位置と姿勢を決める のでも
 どちらでも良いので,考えやすい方法で配置関係を決めます.
 
 ここで,「カメラでの撮影」という話も自分に都合がよい形に決めます.
 (遠近感のある絵ができるカメラを考えれば,最終的な結果は「射影変換」に,
  遠近感のない絵ができるカメラを考えれば,最終的な結果は「アフィン変換」になるかと思います.)

(3) (2)で撮影された仮想的な画像上での座標と,最終的にあなたのソフト上で表示したい世界(ウィンドウのクライアント領域の座標とか?)との
 対応づけを「都合が良いように」決めます.

Name: sereparu
[URL]
かけだし(2,351 ポイント)
Date: 2017年3月19日(日) 13:06
No: 7
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

ソースの改良を色々と試みたところ、X軸とZ軸の同時回転、Y軸とZ軸の同時回転は
望み通りの描画結果を得られるようになりました。
(上記アニメーションで言うと①~③、⑤~⑥は実現しました)

しかし、X軸とY軸の同時回転、X軸とY軸とZ軸の同時回転は、依然として望んだ結果が得られません。
X軸とY軸を同時回転すると、画像が拡大、縮小するのみで、回転するときの奥行きを表現できていません。
X軸とY軸の同時回転が上手くいかないので、当然、X軸とY軸とZ軸の回転もおかしくなっています。

やっぱり難しいのかもしれませんが、あと少し何かを加えれば完成しそうな気がするだけに
なかなか諦めることができないです。

改良したソースは以下の通りです。
回転角度をラジアンに変換する式と、回転後の座標を求める式を変更しています。
望む描画像と見比べつつ、感覚で修正しているので、間違っているかもしれませんが。

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "DxLib.h"
#include <math.h>
 
// Π(パイ)
#define PI 3.1415926535897932384626433832795f
 
// 回転描画処理
extern void kaiten();
 
extern int size_x = 0; // 画像のxサイズ
extern int size_y = 0; // 画像のyサイズ
extern float x = 320;  // 画像の中心x座標
extern float y = 240;  // 画像の中心y座標
extern int rota_x = 0; // x軸回転角度
extern int rota_y = 0; // y軸回転角度
extern int rota_z = 0; // z軸回転角度
 
extern int graph = 0;  // グラフィックハンドル
 
// WinMain 関数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    //ウィンドウモードに変更
    ChangeWindowMode(TRUE) ;
   
    // DXライブラリ初期化処理 エラーが起きたら終了
    if(DxLib_Init() == -1) {
        return -1;
    }
 
    // 描画先を裏画面に設定
    SetDrawScreen(DX_SCREEN_BACK);
 
    // グラフィックハンドルの設定
    graph = LoadGraph("test.png");
    GetGraphSize(graph, &size_x, &size_y);
 
    while (0 == ProcessMessage() && 0 == ClearDrawScreen() &&
        0 == CheckHitKey(KEY_INPUT_ESCAPE)) {
 
        // 回転描画処理
        kaiten();
       
        // 回転角度加算
//        rota_x++;
//        rota_y++;
//        rota_z++;
 
        ScreenFlip();
    }
 
    DxLib_End(); // DXライブラリ使用の終了処理
    return 0;    // ソフトの終了
}
 
// 回転描画処理
void kaiten()
{
    // 回転後の座標
    int X = 0;
    int Y = 0;
 
    // 各回転角度をラジアンに変換
    double radi_x = (90 + rota_x) * PI / 180.0;
    double radi_y = (90 + rota_y) * PI / 180.0;
    double radi_z = rota_z * PI / 180.0;
 
    X = -(size_x / 2) * cos(radi_z) * sin(radi_y) - -(size_y / 2) * sin(-radi_z) * sin(radi_y);
    Y = -(size_x / 2) * sin(-radi_z) * sin(radi_x) + -(size_y / 2) * cos(radi_z) * sin(radi_x);
    int ax = x + X;
    int ay = y + Y;
 
    X = (size_x / 2) * cos(radi_z) * sin(radi_y) - -(size_y / 2) * sin(-radi_z) * sin(radi_y);
    Y = (size_x / 2) * sin(-radi_z) * sin(radi_x) + -(size_y / 2) * cos(radi_z) * sin(radi_x);
    int bx = x + X;
    int by = y + Y;
 
    X = (size_x / 2) * cos(radi_z) * sin(radi_y) - (size_y / 2) * sin(-radi_z) * sin(radi_y);
    Y = (size_x / 2) * sin(-radi_z) * sin(radi_x) + (size_y / 2) * cos(radi_z) * sin(radi_x);
    int cx = x + X;
    int cy = y + Y;
 
    X = -(size_x / 2) * cos(radi_z) * sin(radi_y) - (size_y / 2) * sin(-radi_z) * sin(radi_y);
    Y = -(size_x / 2) * sin(-radi_z) * sin(radi_x) + (size_y / 2) * cos(radi_z) * sin(radi_x);
    int dx = x + X;
    int dy = y + Y;
 
    // 描画
    DrawModiGraph(ax, ay, bx, by, cx, cy, dx, dy, graph, TRUE);
}

Name: usao
[URL]
ハッカー(126,567 ポイント)
Date: 2017年3月19日(日) 14:32
No: 8
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

>X軸とY軸とZ軸の同時回転

この表現がとても曖昧なのが気になります.

ある物を手渡されて,
「これをX軸周りに回せ」と言われたならば,まぁ,話がわかりますが,
「これを3軸周りに同時に回せ」と言われたら,どうするのが正解なのかがわかりません.


「同時」ではなく,順番がある話:
 (1)まずX軸まわりに30度回転させ,
 (2)次にその状態からY軸まわりに20度回転させ,
 (3)最後に,その状態からZ軸周りに7度回転させる
ではダメなのでしょうか.
あるいは,
「回転軸とその周りの回転角度」という与え方ではダメでしょうか.

Name: sereparu
[URL]
かけだし(2,351 ポイント)
Date: 2017年3月19日(日) 18:01
No: 9
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

usaoさん
表現が分りづらくてすみません。

同時回転というのは、上記ソースの46~48行目の「回転角度加算」の部分の
コメントアウトを複数行外して、複数の回転角度が同時に加算される状態のことです。
例えば、X軸とY軸を同時回転させる場合は、rota_x++とrota_y++のコメントアウトを外します。

今のソースだと、すべての軸を回転させた結果の座標を一度に計算しているので
usaoさんのおっしゃる通り、回転する順番を考慮して
(x, y)をX軸まわりに回転させた座標を(x1, y1)、(x1, y1)をY軸まわりに回転させた座標を(x2, y2)
というように、座標を順番に計算させれば上手くいくかもしれません。
アドバイスありがとうございます。一度試してみます。

あと、すみません。「回転軸とその周りの回転角度」とはどういう意味でしょうか?

【追記】
リンク先のアニメーションが見れなかったそうなので、添付ファイルに追加してみました。
アニメーションをご覧いただければ、多分想像しやすいと思うのですが。
添付ファイル
animation.gif
animation.gif (150.15 KiB) 表示数: 813 回

Name: usao
[URL]
ハッカー(126,567 ポイント)
Date: 2017年3月21日(火) 10:12
No: 10
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

> (x, y)をX軸まわりに回転させた座標を(x1, y1)、(x1, y1)をY軸まわりに回転させた座標を(x2, y2)
> というように、座標を順番に計算させれば上手くいくかもしれません。

そういう方法で良いならば(やりたいことと合っているならば)
「3次元の回転マトリクス」,「オイラー角」,「ロール,ピッチ,ヨー」みたいな単語で検索すれば
情報(というか数式)が見つかると思うので,それを使うと良いかと.

繰り返しになりますが,
 2次元(元画像) → 3次元(回転を考える世界) → 2次元(最終表示)
という感じで,回転は3次元世界で考える必要があると思います.
「X軸まわりに回転させた座標(X1,Y1,Z1)をY軸まわりに回転させて(X2,Y2,Z2)にしてそれを…」という感じ.


> あと、すみません。「回転軸とその周りの回転角度」とはどういう意味でしょうか?

割とそのままの意味ですが…
例えばイメージとしては, リンゴか何かにぐさっと串を刺してそれを軸にして回す  という感じのことです.
(「回したい方向(=軸)」が明確にわかっているのであれば,回転をわざわざ3つの角度にばらして指定する必要は無いですよね)
こちらは,「任意軸周りの回転」だとか,「クオータニオン(四元数)」みたいな単語で検索すると良いかと.


#数式の意味が不明でも,とりあえず,
 回転後(X',Y',Z') = 関数( 回転前(X,Y,Z) ; 回転具合指定パラメタ )
というブラックボックス的な"道具"に仕立て上げれば,どうにかなるかと.

Name: Dixq (管理人)
(管理人)
[URL]
ウィザード(1,473,823 ポイント)
Date: 2017年3月25日(土) 22:41
No: 11
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

そんなに難しいことをしなくてもDXライブラリで3D描画することは可能ですが、それではだめなんでしょうか?

Name: sereparu
[URL]
かけだし(2,351 ポイント)
Date: 2017年3月26日(日) 11:19
No: 12
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

usaoさん
何度も丁寧なご回答ありがとうございます。
回転を表現する方法は色々あるんですね。
ご回答頂いた内容を調べれば、実現したいことに近い内容が見つかるかもしれません。

Dixq(管理人)さん
ご回答ありがとうございます。
3D関数を使ずにDrawModiGraphにしているのは、最初に書きましたように
・二次元の座標上で3Dを表現したい
・画像の四つの頂点の座標を当たり判定に使用したい
という理由があります。
3D関数だと3D空間上の座標になってしまうため、実現したいことと異なります。

また、前回の書き込みで上手くいかなかったX軸とY軸の同時回転もソースの修正で実現でき
後はX軸とY軸とZ軸の同時回転さえできれば解決というところまで来ているので
ここで諦めて別の関数を使うのは腑に落ちないという気持ちもあります。

とりあえず、X軸とY軸の同時回転ができるようになったソースを載せておきます。
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include "DxLib.h"
#include <math.h>
 
// Π(パイ)
#define PI 3.1415926535897932384626433832795f
 
// 回転描画処理
extern void kaiten();
 
extern int size_x = 0; // 画像のxサイズ
extern int size_y = 0; // 画像のyサイズ
extern float x = 320;  // 画像の中心x座標
extern float y = 240;  // 画像の中心y座標
extern int rota_x = 0; // x軸回転角度
extern int rota_y = 0; // y軸回転角度
extern int rota_z = 0; // z軸回転角度
 
extern int graph = 0;  // グラフィックハンドル
 
// WinMain 関数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    //ウィンドウモードに変更
    ChangeWindowMode(TRUE) ;
   
    // DXライブラリ初期化処理 エラーが起きたら終了
    if(DxLib_Init() == -1) {
        return -1;
    }
 
    // 描画先を裏画面に設定
    SetDrawScreen(DX_SCREEN_BACK);
 
    // グラフィックハンドルの設定
    graph = LoadGraph("test.png");
    GetGraphSize(graph, &size_x, &size_y);
 
    while (0 == ProcessMessage() && 0 == ClearDrawScreen() &&
        0 == CheckHitKey(KEY_INPUT_ESCAPE)) {
 
        // 回転描画処理
        kaiten();
       
        // 回転角度加算
        rota_x++;
        rota_y++;
        rota_z++;
 
        ScreenFlip();
    }
 
    DxLib_End(); // DXライブラリ使用の終了処理
    return 0;    // ソフトの終了
}
 
// 回転描画処理
void kaiten()
{
    // 回転後の座標
    int X = 0;
    int Y = 0;
 
    // 各回転角度をラジアンに変換
    double radi_x = (90 + rota_x) * PI / 180.0;
    double radi_x2 = rota_x * PI / 180.0;
    double radi_y = (90 + rota_y) * PI / 180.0;
    double radi_z = rota_z * PI / 180.0;
 
    X = -(size_x / 2) * cos(radi_z) - -(size_y / 2) * sin(-radi_z);
    Y = -(size_x / 2) * sin(-radi_z) + -(size_y / 2) * cos(radi_z);
    int ax = x + X * sin(radi_y);
    int ay = y + Y * sin(radi_x) + (size_x / 2) * cos(radi_y) * sin(-radi_x2);
 
    X = (size_x / 2) * cos(radi_z) - -(size_y / 2) * sin(-radi_z);
    Y = (size_x / 2) * sin(-radi_z) + -(size_y / 2) * cos(radi_z);
    int bx = x + X * sin(radi_y);
    int by = y + Y * sin(radi_x) - (size_x / 2) * cos(radi_y) * sin(-radi_x2);
 
    X = (size_x / 2) * cos(radi_z) - (size_y / 2) * sin(-radi_z);
    Y = (size_x / 2) * sin(-radi_z) + (size_y / 2) * cos(radi_z);
    int cx = x + X * sin(radi_y);
    int cy = y + Y * sin(radi_x) - (size_x / 2) * cos(radi_y) * sin(-radi_x2);
 
    X = -(size_x / 2) * cos(radi_z) - (size_y / 2) * sin(-radi_z);
    Y = -(size_x / 2) * sin(-radi_z) + (size_y / 2) * cos(radi_z);
    int dx = x + X * sin(radi_y);
    int dy = y + Y * sin(radi_x) + (size_x / 2) * cos(radi_y) * sin(-radi_x2);
 
    // 描画
    DrawModiGraph(ax, ay, bx, by, cx, cy, dx, dy, graph, TRUE);
}

Name: qwea
[URL]
熟練のプログラマー(46,916 ポイント)
Date: 2017年3月27日(月) 17:47
No: 13
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

流れをぶった切る形で申し訳ないのですが、
自分のゲームでは行列を使って頂点を計算しています。
計算する関数はDXLIBが用意してくれています。
以下サンプルを乗せました。参考になりましたら幸いです。

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "DxLib.h"
 
#define WIDTH   50
#define HEIGHT  50
 
int g_image_handle = -1;
 
// 回転描画
void Draw3DRot(float _x, float _y, float _x_rot, float _y_rot, float _z_rot)
{
    VECTOR m_pos[4] = {
        {-WIDTH/2-HEIGHT/20.f},   // 左上頂点
        {WIDTH/2,   -HEIGHT/20.f},   // 右上頂点
        {WIDTH/2,   HEIGHT/2,   0.f},   // 右下頂点
        {-WIDTH/2,  HEIGHT/2,   0.f},   // 左下頂点
    };
    MATRIX transMat, rotMat, mulMat;
 
    CreateTranslationMatrix(&transMat, _x, _y, 0.f);
    CreateRotationYXZMatrix(&rotMat, _x_rot, _y_rot, _z_rot);
 
    // 単位行列
    CreateIdentityMatrix(&mulMat);
    // 回転させる
    CreateMultiplyMatrix(&mulMat, &mulMat, &rotMat);
    // 移動させる
    CreateMultiplyMatrix(&mulMat, &mulMat, &transMat);
 
    // 各頂点に行列を適用
    for(int i = 0; i < 4; i++)
    {
        VectorTransform(&m_pos[i], &m_pos[i], &mulMat);
    }
   
    DrawModiGraphF(m_pos[0].x, m_pos[0].y, m_pos[1].x, m_pos[1].y, m_pos[2].x, m_pos[2].y, m_pos[3].x, m_pos[3].y, g_image_handle, TRUE);
}
 
// WinMain
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    float ang = 0;
 
    // ウインドウモードで起動
    ChangeWindowMode( TRUE );
 
    // ライブラリの初期化
    if( DxLib_Init() < 0 )
        return -1;
 
    // 描画先を裏画面にする
    SetDrawScreen( DX_SCREEN_BACK );
 
    g_image_handle = LoadGraph("test.png");
 
    // ESCキーが押されるか、ウインドウが閉じられるまでループ
    while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
    {
        // 画面をクリア
        ClearDrawScreen();
 
        float x = 640/7/2;
        float w = 640/7;
        float y = 480/2;
        Draw3DRot(x+w*0, y, ang, 0, 0);
        Draw3DRot(x+w*1, y, 0, ang, 0);
        Draw3DRot(x+w*2, y, 0, 0, ang);
        Draw3DRot(x+w*3, y, ang, ang, 0);
        Draw3DRot(x+w*4, y, ang, 0, ang);
        Draw3DRot(x+w*5, y, 0, ang, ang);
        Draw3DRot(x+w*6, y, ang, ang, ang);
 
        ang -= 0.05f;
 
        // 裏画面の内容を表画面に反映
        ScreenFlip();
    }
 
    // ライブラリの後始末
    DxLib_End() ;
 
    // ソフト終了
    return 0 ;
}

Name: sereparu
[URL]
かけだし(2,351 ポイント)
Date: 2017年3月27日(月) 23:17
No: 14
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

qweaさん
ご回答ありがとうございます。
ご提示いただいたサンプルは実現したいことにほぼ近いです。
既存のソースをなるべく使いたいという気持ちにとらわれていて
行列を使うことを考えていませんでした。
サンプルを参考にして、行列を使って自分のソースを改良してみようと思います。

Name: sereparu
[URL]
かけだし(2,351 ポイント)
Date: 2017年3月30日(木) 23:50
No: 15
(OFFLINE)

 Re: DXライブラリのDrawModiGraphで画像を三次元的に回転させるには?

[解決!]

qweaさんのサンプルをほぼそのまま(Draw3DRotの引数を0~359の角度で指定できるように改造して)使用することにしました。
これで望んだ通りの処理が実現しましたので、解決とさせていただきます。
アドバイスをくださった皆様、本当にありがとうございました。


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[19人]