物体を三次元で回転させたいです

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
taketoshi
記事: 222
登録日時: 14年前
住所: 日本国

物体を三次元で回転させたいです

#1

投稿記事 by taketoshi » 13年前

次の二つの動きを融合させたいです

この回転と
[youtube][/youtube]

この回転です
[youtube][/youtube]


二つを融合させて自然に桜の花びらが舞い散るようにしたいのですが、どのような処理が必要になってくるのでしょうか?
現在以下のようにそれぞれコードを書いていますが、X,Y軸の推移のさせ方がさっぱりわからないです。
サンプルコードなどありましたらうれしいです。詳しい方お願いいたします。

時計回りに回転させているコード
► スポイラーを表示

くるくる回転させているコード
► スポイラーを表示

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: 物体を三次元で回転させたいです

#2

投稿記事 by ISLe » 13年前

それぞれの回転を行列で表現して、それぞれの行列を掛けて求まった行列を使って座標変換してやると良いです。
頂点変換なので行列の代わりにクォータニオン使えば計算量減らせると思います。

アバター
あたっしゅ
記事: 667
登録日時: 14年前
住所: 東京23区
連絡を取る:

Re: 物体を三次元で回転させたいです

#3

投稿記事 by あたっしゅ » 13年前

コード:

#include "DxLib.h"
#include <math.h>
 
#define Rate_X 0.55
#define Rate_y 0.83
 
#define PI 3.14
 
class CSakura
{
private:
    int nHandle;        //画像ハンドル
    int nImageSizeX;    //画像Xサイズ
    int nImageSizeY;    //画像Yサイズ
    float x[2];         //X軸の実座標
    float y[2];         //Y軸の実座標
    double locate[4][2];// 追加 実座標
    int accx;           //X加速度        
    int accy;           //Y加速度
    float nRotateX;     //X軸の回転速度
    float nRotateY;     //Y軸の回転速度
    bool bRotateX;      //回転フラグ
    bool bRotateY;		// 追加
    bool bRotateTime;   // 追加 X,Yどちらに回転させるか
    float nExRate;      //画像の倍率
    float nAngle;       //角度
    float Rate[4];		// 追加 
public:
    CSakura();           //コンストラクタ
    void ShowImage();   //画像描写
    void SetStatus();   //加速
    void Rotate1();     // 追加 平面回転運動
};
 
 
//コンストラクタ
//初期パラメータの設定
CSakura::CSakura(){ 
    RECT rc;
    GetWindowCRect(&rc);
 
    //画像情報の読み込み
    nHandle = LoadGraph("画像//sakura.png");
    GetGraphSize(nHandle,&nImageSizeX,&nImageSizeY);
 
    //画像倍率の取得
    nExRate = rand() % 100 * 0.01 + 0.3;
    //倍画像率の調整
    nImageSizeX *= nExRate;
    nImageSizeY *= nExRate;
 
    //出現位置の調整
    if((rand() % 10) / 2 == 0){
    //X軸の初期位置、Y軸は0
        x[0] = 0;
        x[1] = x[0] + nImageSizeX;
        y[0] = 0;
        y[1] = y[0] + nImageSizeY;
    }else{
    //Y軸の初期位置、X軸は0
        y[0] = 0;
        y[1] = y[0] + nImageSizeY;
        x[0] = 0;
        x[1] = x[0] + nImageSizeX;
    }
    //X加速度の取得
    accx = (rand() % 10) * 0.5 +1;
 
    //Y加速度の取得
    accy = rand() % 10 + 0.5 +1;
 
    //X軸回転速度の取得
    nRotateX = (float)GetRand(20) * 0.2;
    
    //Y軸回転速度の取得
    nRotateY = (float)GetRand(20) * 0.2;
 
    //回転フラグの取得
    bRotateX = 0;

    nAngle = 1; // 追加
}
 
//描写関数
void CSakura::ShowImage(){
	DrawModiGraph(
		locate[0][0],locate[0][1],            //左上
        locate[1][0],locate[1][1] ,           //右上
        locate[3][0],locate[3][1],            //右下
        locate[2][0],locate[2][1],            //左下
        nHandle,true
	);
}


// 追加 平面回転運動
void CSakura::Rotate1(){
 
    float X,Y;

	//画像の回転処理
    X = -(nImageSizeX / 2) * cos( nAngle * PI / 180.0) - -(nImageSizeY / 2) * sin( nAngle * PI / 180.0);
    Y = -(nImageSizeX / 2) * sin( nAngle * PI / 180.0) + -(nImageSizeY / 2) * cos( nAngle * PI / 180.0);
    locate[0][0] = x[0] + X;
    locate[0][1] = y[0] + Y;
 
    X = (nImageSizeX / 2) * cos( nAngle * PI / 180.0) - -(nImageSizeY / 2) * sin( nAngle * PI / 180.0);
    Y = (nImageSizeX / 2) * sin( nAngle * PI / 180.0) + -(nImageSizeY / 2) * cos( nAngle * PI / 180.0);
    locate[1][0] = x[0] + X;
    locate[1][1] = y[1] + Y;
 
    X = -(nImageSizeX / 2) * cos( nAngle * PI / 180.0) - (nImageSizeY / 2) * sin( nAngle * PI / 180.0);
    Y = -(nImageSizeX / 2) * sin( nAngle * PI / 180.0) + (nImageSizeY / 2) * cos( nAngle * PI / 180.0);
    locate[2][0] = x[1] + X;
    locate[2][1] = y[1] + Y;
 
    X = (nImageSizeX / 2) * cos( nAngle * PI / 180.0) - (nImageSizeY / 2) * sin( nAngle * PI / 180.0);
    Y = (nImageSizeX / 2) * sin( nAngle * PI / 180.0) + (nImageSizeY / 2) * cos( nAngle * PI / 180.0);
    locate[3][0] = x[0] + X;
    locate[3][1] = y[1] + Y;

	//角度の増加
    nAngle++;
    if(nAngle == 360){
        nAngle = 0;
    }
}


//移動設定関数
void CSakura::SetStatus(){
    
    RECT rc;
 
    //X,Y軸の加速
    //x[0] += accx;
    //x[1] += accx;
    //y[0] += accy;
    //y[1] += accy;
 
    //X軸に沿って画像を回転させる
    x[0] += nRotateX;
    x[1] -= nRotateX;
    //if(nRotateX < 0.5){
        //X軸に沿って画像を回転させる
        //y[0] += nRotateY;
        //y[1] -= nRotateY;
    //}
 
    //画像の回転方向の切り替え
    if(x[0] - x[1] > nImageSizeX && bRotateX == 0){
        bRotateX = 1;
        nRotateX *= -1;
        nRotateY *= -1;
    }else if(x[1] - x[0] > nImageSizeX && bRotateX == 1){
        bRotateX = 0;
        nRotateX *= -1;
        nRotateY *= -1;
    }else{
    }
 
    //落下しきった花びらのリサイクル設定
    GetWindowCRect(&rc);
    if(y[1] + nImageSizeY > rc.bottom || x[1] + nImageSizeX > rc.right){
        //出現位置の調整
        if((rand() % 10) / 2 == 0){
        //X軸の初期位置、Y軸は0
            x[0] = (rand() % ((rc.right - rc.left) - 10)) / 2 + 200;
            x[1] = x[0] + nImageSizeX;
            y[0] = nImageSizeY * -1;
            y[1] = y[0] + nImageSizeY;
        }else{
        //Y軸の初期位置、X軸は0
            y[0] = (rand() % ((rc.right - rc.left) - 10)) / 2 - 200;
            y[1] = y[0] + nImageSizeY;
            x[0] = nImageSizeX * -1;
            x[1] = x[0] + nImageSizeX;
        }
    }
 
    DrawFormatString(300,100,RGB(255,255,255),"座標 左上X[%f]Y[%f]",x[0],y[0]);
    DrawFormatString(300,150,RGB(255,255,255),"座標 右上X[%f]Y[%f]",x[1],y[0]);
    DrawFormatString(300,200,RGB(255,255,255),"座標 右下X[%f]Y[%f]",x[1],y[1]);
    DrawFormatString(300,250,RGB(255,255,255),"座標 左下X[%f]Y[%f]",x[0],y[1]);
    DrawFormatString(300,350,RGB(255,255,255),"フラグ %d",bRotateX);
}
 
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
 
    ChangeWindowMode(TRUE);
    DxLib_Init();
    SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
 
    int i = 0,n;
    CSakura sk[200];
 
    // while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
    while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
        //桜の描写タイミングを調整
        if(i <1){
            if(rand() % 10 != 7){
                i++;
            }
        }
        for(n = 0;n < i; n++){
            sk[n].ShowImage();
            sk[n].SetStatus();
            sk[n].Rotate1();
        }
        
        ScreenFlip(); //裏画面を表画面に反映
 
    }
    
    DxLib_End(); // DXライブラリ終了処理
    return 0;
}
2つのコードを組み合わせて、ちょっぴり手を加えてみました。
まだ、ちょっと不自然な感じですが。
VTuber:
[香車]東上☆Aho(暎帆)☆海美
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。

taketoshi
記事: 222
登録日時: 14年前
住所: 日本国

Re: 物体を三次元で回転させたいです

#4

投稿記事 by taketoshi » 13年前

お二方、回答ありがとうございます。
仕事の関係で暫くPCを触れませんでした。回答頂いておいて、遅くなって申し訳ないです。


>ISLeさん
キーワードの提示ありがとうございます。
ググって調べてみました。自分には数式に意味が分からなかったので
少し時間をかけて読み解いて見ます。


>あたっしゅさん
ソースコードの提示ありがとうございます。
コピペして動かしてみましたが、何か違いますね/_\
桜の花びらの落下方法を根本的にも考え直して見ます。


一応解決とさせて頂きます。ご教授ありがとうございます。

閉鎖

“C言語何でも質問掲示板” へ戻る