ホーム 主筆 その他ソフト その他情報 Syuhitu.org English

Windows関連

スクリーンセーバー作成法

半透明ウインドウの性能

bootfont.bin

キャビネット形式

ウインドウスタイルをいじる

Java製ソフトをServiceに登録する

イベントログにメッセージを出力する

コントロールパネルにアイコンを追加する

スクリプトによる拡張1

スクリプトによる拡張2

ガジェットの作成

大容量メモリ

メモリ搭載量の下限に挑む

スパースファイルにする

表示されるアイコンの種類を調べてみた

メモリマップIOとエラー処理

ファイルを作る順番と速度の関係

Cryptography API: Next Generationを使う

Windows 10のアクセントカラー

iSCSIディスクにバックアップを取る

サーバプロセスを分離して実装する

サーバプロセスを分離して実装する - F#

レジストリに大量に書き込む

Solaris関連

OpenGL

Solaris設定

ディレクトリの読み込み

主筆プラグイン開発

マルチスレッドでの開発

door

音を出す

Blade100の正しい虐め方

パッケージの作成

画像入出力

BMPファイル

ICOファイル

ANIファイル

JPEGファイル

減色アルゴリズム

減色アルゴリズムの並列化

その他アルゴリズムなど

自由軸回転

Base64

文字列操作

CPU利用率の取得

正規表現ライブラリ

メタボールを作る

メタボールを作る2

正規表現とNFA・DFA

C言語の構文解析

液晶ディスプレイを解体してみた

iSCSIの理論と実装

単一フォルダにファイルを沢山作る

USB-HUBのカスケード接続

SafeIntの性能

VHDファイルのフォーマット

USBメモリに書き込み続けてみた

自由軸回転を行う

1.オイラー角

OpenGLで回転を行うには、普通はglRotate関数を使用します。しかし、それだとX,Y,Zの各軸での回転しかできません。世の中一般ではこのことをオイラー角表現と言うそうです、

X・Y・Zの各軸での回転

オイラー角での回転

普通はこれでもいいのですが、時々そうでないことがあります。「こう回したい」と思っても、うまくいかない、つまり

「あぁ〜んそうじゃないのに!」

と叫びたくなることもある訳です。

斜めに回したい絵

矢印のように斜めに回したくなることもある。

そして、そういう時に役に立つのがこの自由軸回転というやつです。世の中一般では、自由軸回転と下記のクォータニオンとは別物と見なすようですが、私にはよく解りません。

2.クォータニオン

ところで、クォータニオンなるものを耳にして、なんか使えそうだと思い、調べたことがある方はお分かりだと思いますが、

「理解できない」

まず、Webで検索してもほとんど有用な情報は出てきません。つまり、「どうしたら自分が思っているとおりに回転できるのか」という回答はなかなか有りません。(有るんでしょうが、見つかりません。ついでに言うとこのページもその一つなんだろうな。)

あるのはクォータニオンという語を連発しているだけで、まったく説明していないか、そうでなければ、意味不明な数式を書き連ね、自己満足に陥っているか、いずれにせよ役に立たない情報ばかり。普通の人間にならそれで理解できるのかも知れないのですが、やっとこ商業高校を出たような愚鈍な人間には到底理解できません。別に私はクォータニオンを知りたいのではなく、回転を行いたいだけなのですが。ねぇ。

3.とりあえず、答え

愚痴は置いておいて、私なりにまとめた「答え」を言います。

#define RADIAN( n ) ( ( n ) * ( 3.1415926535897932384626 / 180.0 ) )

void FreeRotate( float n[3], float r )
{
    float v[16];
    float w =(float)cos( RADIAN( r ) / 2.0f );
    float w2 = w * w;
    float s = (float)sin( RADIAN( r ) / 2.0f );
    float x = n[0] * s;
    float y = n[1] * s;
    float z = n[2] * s;
    float x2 = x * x;
    float y2 = y * y;
    float z2 = z * z;

    v[0] = w2 + x2 - y2 - z2;
    v[4] = 2 * ( ( x * y ) - ( w * z ) );
    v[8] = 2 * ( ( x * z ) + ( w * y ) );
    v[12] = 0.0f;

    v[1] = 2 * ( ( x * y ) + ( w * z ) );
    v[5] = w2 - x2 + y2 - z2;
    v[9] = 2 * ( ( y * z ) - ( w * x ) );
    v[13] = 0.0f;

    v[2] = 2 * ( ( x * z ) - ( w * y ) );
    v[6] = 2 * ( ( y * z ) + ( w * x ) );
    v[10] = w2 - x2 - y2 + z2;
    v[14] = 0.0f;

    v[3] = 0.0f;
    v[7] = 0.0f;
    v[11] = 0.0f;
    v[15] = 1.0f;

    glMultMatrixf( v );
}
この関数を、プログラム中の適当なことろに配置して、呼び出してやってください。あとは勝手に何とかしてくれると思います。

引数のnは回転の中心となる軸をあらわす単位ベクトルです。rは回転したい角度(0から360度のやつ)を指定します。

引数として渡す単位ベクトルがひとつしかないところを見ると、この関数は原点から伸びる軸を中心とした回転しかできない、ということになりそうです。

でも、回転軸の平行移動は何とかなるもので、以下のようにしてあげるといい感じになります。

glTranslatef( x, y, z ); /* 本来回転軸にいてほしい位置まで、移動 */
FreeRotate( n, v ); /* 回す */
glTranslatef( -x, -y, -z ); /* 元に戻す */
/* 描画するプログラム */

つまり、回転軸を動かしたい位置まで平行移動して、その後、何も描画せずに元に戻します。当然、FreeRotateの影響がほしいので、glPushMatrixとglPopMatrixを使ってはいけません。

4.関数の解説

はっきり言ってしまいます、私は上記の関数が何をしているか理解していません

だから、この関数が何をしているのか、質問しないでください。本当に知りたい人は別のクォータニオンを説明している本なり何なりで勉強してください。

5.その他

上記の関数内でいきなりglMultMatrix関数を呼び出していますが、別にここで呼び出す必要はありません。引数か何かで、計算結果の配列を返すようにして、必要なところでglMultMatrixを呼び出してあげるのが良いのではないかと思います。

6.注意事項

何度も言いますが、私は、この関数を理解していません。

なので、バグがあるかどうかも解りません。

運用は各自の判断で、行ってください。

というか、ここに書いてあることを当てにしないほうがいいのでは?

7.とりあえず、サンプル

あまり、意味はないけど、サンプルプログラムを公開します。

FRSample.cab 13KB


連絡先 - サイトマップ - 更新履歴
Copyright (C)  2000 - 2016 nabiki_t All Rights Reserved.