クオータニオンで真横、真正面に移動する

#ifndef MIFFY_FIXED_VIEW
#define MIFFY_FIXED_VIEW
#include "matrix.h"
#include "quaternion.h"
using namespace miffy;
/// quaternion.hとmatrix.hを使用して、オブジェクトをある特定のビューにきちっとさせるためのユーティリティ
/*!
        本当はGoogle EarthやBlenderみたいになめらかに連続的に視点を変えたいが、
        これは一瞬でぱっと瞬間移動する状態になっている。
        CTransFormというクラスを作ったけど、遅くなったのでやめたい。CTransFormのせいで遅くなったのかはわからないが、
        CTransFormというクラスを回避するためにユーティリティを作った。
        FixedViewにするという作業は、毎フレーム行うようなことじゃないから、外部ライブラリ化してもあまり影響がないと思ってライブラリ化した。
*/
namespace fixedview{
    /// 内部的に使用する。 同じ作業が繰り返しだったがために作っただけ。 外部からは使えなくていいんだけど、namespaceだとそういうことができないなぁ。
    template <typename T>
    void Reset(mat4<T>* _tra,quat<T>* _cquat){
        _tra->m[12]=0.0f;//x
        _tra->m[13]=0.0f;//y
        _cquat->set(1.0f,0.0f,0.0f,0.0f);
    }
    /// z+:画面上 y+:画面奥 x:画面右 プラス方向がすべて奥に行っているという意味でBack
    /*! Descripito:z+:画面上 y+:画面奥 x:画面右 プラス方向がすべて奥に行っているという意味でBack
        @param _tra 平行移動行列を渡す
        @param _rotation 回転行列を渡す
        @param _cquat 現在のクオータニオンを渡す 回転姿勢保存のための変数
        @param _tquat ターゲットクォータニオン
    */
    template <typename T>
    void Back(mat4<T>* _tra,mat4<T>* _rotation,quat<T>* _cquat,quat<T>* _tquat){
        Reset(_tra,_cquat);
        vec3<float> axis=vec3<float>(1.0f,0.0f,0.0f);
        float radian=-0.5f*(float)M_PI*0.5f;
        quat<float> difq(cos(radian),axis.x*sin(radian),axis.y*sin(radian),0.0f);
        _tquat->set(difq.mult(_cquat));
        _tquat->toMat4(_rotation->m);
        _cquat->set(_tquat);//一旦front viewにする。
        axis=vec3<float>(0.0f,1.0f,0.0f);
        radian=(float)M_PI*0.5f;
        difq.set(cos(radian),axis.x*sin(radian),axis.y*sin(radian),0.0f);
        _tquat->set(difq.mult(_cquat));
        _tquat->toMat4(_rotation->m);    
        _cquat->set(_tquat);
    }
    /// z+:奥 y+:画面上 x+:画面左 の状態にする
    /*! 
        @param _tra 平行移動行列を渡す
        @param _rotation 回転行列を渡す
        @param _quat 現在のクオータニオンを渡す
    */
    template <typename T>
    void Bottom(mat4<T>* _tra,mat4<T>* _rotation,quat<T>* _quat){
        Reset(_tra,_quat);
        _quat->toMat4(_rotation->m);
    }
    /// z+:画面上 y+:画面手前 x:画面左 プラス方向がすべて手間に向かっている意味でFront
    /*! 
        @param _tra 平行移動行列を渡す
        @param _rotation 回転行列を渡す
        @param _cquat 現在のクオータニオンを渡す 回転姿勢保存のための変数
        @param _tquat ターゲットクォータニオン
    */
    template <typename T>
    void Front(mat4<T>* _tra,mat4<T>* _rotation,quat<T>* _cquat,quat<T>* _tquat){
        Reset(_tra,_cquat);
        vec3<float> axis=vec3<float>(1.0f,0.0f,0.0f);
        float radian=-0.5f*(float)M_PI*0.5f;
        quat<float> difq(cos(radian),axis.x*sin(radian),axis.y*sin(radian),0.0f);
        _tquat->set(difq.mult(_cquat));
        _tquat->toMat4(_rotation->m);    
        _cquat->set(_tquat);
    }
    /// 初期状態と同じ z手前 y画面下 x:画面左 初期状態とおなじなのになんで、Bottomより複雑になってしまったんだろう。謎    
    /*! @param _tra 平行移動行列を渡す
        @param _rotation 回転行列を渡す
        @param _cquat 現在のクオータニオンを渡す 回転姿勢保存のための変数
        @param _tquat ターゲットクォータニオン
    */
    template <typename T>
    void Top(mat4<T>* _tra,mat4<T>* _rotation,quat<T>* _cquat,quat<T>* _tquat){//なぜデフォルトと同じなのに、こんなややこしい操作が必要なんだろう。。。
        Reset(_tra,_cquat);
        vec3<float> axis=vec3<float>(1.0f,0.0f,0.0f);
        float radian=(float)M_PI*0.5f;
        quat<float> difq(cos(radian),axis.x*sin(radian),axis.y*sin(radian),0.0f);
        _tquat->set(difq.mult(_cquat));
        _tquat->toMat4(_rotation->m);    
        _cquat->set(_tquat);
    }
    /// オブジェクトの右側を見る。 z+:画面上 y+:画面左 x+:画面奥 になる
    /*! @param _tra 平行移動行列を渡す
        @param _rotation 回転行列を渡す
        @param _cquat 現在のクオータニオンを渡す 回転姿勢保存のための変数
        @param _tquat ターゲットクォータニオン
    */
    template <typename T>
    void Right(mat4<T>* _tra,mat4<T>* _rotation,quat<T>* _cquat,quat<T>* _tquat){
        Reset(_tra,_cquat);
        vec3<float> axis=vec3<float>(1.0f,0.0f,0.0f);
        float radian=-0.5f*(float)M_PI*0.5f;
        quat<float> difq(cos(radian),axis.x*sin(radian),axis.y*sin(radian),0.0f);
        _tquat->set(difq.mult(_cquat));
        _tquat->toMat4(_rotation->m);
        _cquat->set(_tquat);//一旦front viewにする。
        axis=vec3<float>(0.0f,1.0f,0.0f);
        radian=-0.5f*(float)M_PI*0.5f;
        difq.set(cos(radian),axis.x*sin(radian),axis.y*sin(radian),0.0f);
        _tquat->set(difq.mult(_cquat));
        _tquat->toMat4(_rotation->m);    
        _cquat->set(_tquat);
    }
    /// オブジェクトの左側を見る。 z+:画面上 y+:画面左 x+:画面奥 になる
    /*! @param _tra 平行移動行列を渡す
        @param _rotation 回転行列を渡す
        @param _cquat 現在のクオータニオンを渡す 回転姿勢保存のための変数
        @param _tquat ターゲットクォータニオン
    */
    template <typename T>
    void Left(mat4<T>* _tra,mat4<T>* _rotation,quat<T>* _cquat,quat<T>* _tquat){
        Reset(_tra,_cquat);
        vec3<float> axis=vec3<float>(1.0f,0.0f,0.0f);
        float radian=-0.5f*(float)M_PI*0.5f;
        quat<float> difq(cos(radian),axis.x*sin(radian),axis.y*sin(radian),0.0f);
        _tquat->set(difq.mult(_cquat));
        _tquat->toMat4(_rotation->m);
        _cquat->set(_tquat);//一旦front viewにする。
        axis=vec3<float>(0.0f,1.0f,0.0f);
        radian=0.5f*(float)M_PI*0.5f;
        difq.set(cos(radian),axis.x*sin(radian),axis.y*sin(radian),0.0f);
        _tquat->set(difq.mult(_cquat));
        _tquat->toMat4(_rotation->m);    
        _cquat->set(_tquat);
    }
}
#endif
サポートサイト Wikidot.com