「がんばれない」けど「がんばりたい」

ITエンジニアの仕事のこと。AI、機械学習、ディープラーニング。地頭力。車のこと。

回転 Quaternion その3 |3Dプログラミング整理

前々回でやりのこしていた事を検証してみる。

pitch, yaw, rollという言葉で姿勢を表現できると書いたが、 これはQuaternionではなく、オイラー角にあたる。

ではオイラー角とは? オイラー角は、基本は飛行機などの機体の姿勢を示すために使用されていて、 それぞれx, y, z軸に対して何度傾いているか?を示すもの。 らしい。

ゲームエンジンや3Dエンジンによっては、 x,z,x軸といったY軸を抜いているものもあるが、 これは、ある物体を回転させるには2軸あれば実現できるからである。

Quaternionは、このオイラー角を使用して作成出来るため、 用語としてpitch, yaw, rollというオイラー角が出てきているだけ。

オイラー角からQuaternionを作成する事は容易だが、 その逆は難しいらしい。。

前回のコードを少々触って、 オイラー角がとる範囲をoF上ではどういう単位で使用できるのかを 今回は検証してみたい。

「角」という言葉が使用されているので、「度」が単位ではないのか?という想定を描いてみる。

keyPressedでx, y, zキーを押すたびに、 それぞれpitch, yaw, roll値に+1してみた。 そしてデバックウィンドウに現在の値を出力し、 何度(想定)回転したか?が分かるようにした。

今回は動画はアップしていないが、予想どおり、 値が90になった時には、90度回転している事が確認できた!

以下にソースコードを掲載する。

#include "testApp.h"


//  ワールド座標の各x,y,z軸を回転軸として、
//  quaternionによる回転を行ってみる。

//  ------------------------------------------------------------
//  各軸の正規化されたベクトルを定義
ofVec3f Znormal(0,0,1);
ofVec3f Xnormal(1,0,0);
ofVec3f Ynormal(0,1,0);


//  ------------------------------------------------------------
//  roll, pitch, yaw
float roll, pitch, yaw;


//--------------------------------------------------------------
void testApp::setup(){
    
    ofSetFrameRate(60);
    
    //  姿勢の初期値
    roll = 0.0;
    pitch = 0.0;
    yaw = 0.0;
}

//--------------------------------------------------------------
void testApp::update(){
    //  x軸を回転軸とする場合
//    pitch += 1;
    
    //  y軸を回転軸とする場合
//    yaw += 1.0;
    
    //  z軸を回転軸とする場合
//    roll += 1.0;
}

//--------------------------------------------------------------
void testApp::draw(){
    
    ofBackground(0, 0, 0);

    //  ワールド座標上でのx,y,z軸の描画
    ofPushMatrix();
    {
        ofSetLineWidth(10.0);
        
        //  x
        ofSetColor(255, 0, 0);
        ofLine(0.0, 0.0, ofGetWidth(), 0);
        
        //  y
        ofSetColor(0, 255, 0);
        ofLine(0.0, 0.0, 0.0, ofGetHeight());
        
        //  z
        ofSetColor(0, 0, 255);
        ofLine(0, 0, -30.0, 0, 0, 30.0);
    }
    ofPopMatrix();
    
    
    //  各x,y,z軸毎の回転をquaternionとして作成
    ofQuaternion qr (roll, Znormal);
    ofQuaternion qp (pitch, Xnormal);
    ofQuaternion qy (yaw, Ynormal);
    ofQuaternion qt;    //  total quaternion
    
    qt = qr * qp * qy;
    
    
    ofSetLineWidth(1.0);
    ofSetColor(255);
    ofPushMatrix();
    {
        ofNoFill();
        
        //  トータルquaternionよりトータルな回転軸と回転量を取得
        ofVec3f qAxsis;
        float   angle;
        qt.getRotate(angle, qAxsis);
        
        ofTranslate(ofGetWidth()/2, ofGetHeight()/2, 0.0);
        
        //  そして回転
        ofRotate(angle, qAxsis.x, qAxsis.y, qAxsis.z);
        ofSphere(0.0, 0.0, 0.0,  100.0);
        
    }
    ofPopMatrix();
    
}


//--------------------------------------------------------------
void testApp::keyPressed(int key){
    
    if ( key == 'x' ) {
        pitch += 1;
    } else if ( key == 'y' ) {
        yaw += 1;
    } else if ( key == 'z' ) {
        roll += 1;
    } else if ( key == ' ' ) {
        pitch = 0.0;
        yaw = 0.0;
        roll = 0.0;
    }
    
    cout << "x = " << pitch
         << "y = " << yaw
    << "z = " << roll << endl;
}