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

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

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

次にquaternionによる回転を考察する。

quaternion自体の詳細については他サイトや書籍が出ているので、 ここではoFのofQuaternionを通して、その使い方を整理して行きたい。

http://voidinit.blogspot.jp/2012/01/quaternions-and-openframeworks.html このブログではoFのquaternionの使用例が書かれている。 この方法を用いてみる。

quaternionで回転を与える方法として今回用いる方法は、 「オブジェクトの姿勢が数値として分かっている」が条件。

各x,y,z軸に対する姿勢を、pitch, yaw, rollと一般的に言うらしい。 (※この3つの値の単位は、次回に考察する事に。) 次に各x,y,zごとの正規化されたベクトルを定義する。

quaternionは、あくまで任意回転軸で、どのくらいの回転かを表すものである。 その為、必要な条件としては、 オブジェクトが回転する時の回転軸。と、回転量

そのうち任意回転軸に関しては、いきなり回転軸が算出できるのであれば良いが、 ここでの方法では、まず、 x, y, z軸毎に正規化ベクトルを定義し、 それぞれの軸を回転軸としたquaternionを用意する。

そしてquaternion同士の掛け算はquaternionになるという数学定義を利用して、 全ての回転軸毎のquaternionを掛け合わせたトータルなquaternionを算出し、

そのtotalなquaternionから回転軸と回転量を取得し、 オブジェクトを回転させる。

文章で書いていても分かりづらいので、 サンプルコードを下記に示す。

#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);
        
        //  そして回転
        ofRotate(angle, qAxsis.x, qAxsis.y, qAxsis.z);
        ofSphere(ofGetWidth()/2, ofGetHeight()/2, 0.0,  100.0);
        
    }
    ofPopMatrix();   
}