マウスでグリグリ

3DCGArtsでポリゴンオブジェクトをグリグリ回転するような操作をトラックボール操作というらしい。なるほどねー、言われてみれば確かにトラックボールだ。

今回はそれをjME(jMonkeyEngine)で実装してみた。

最初は3Dの一般的なところから検索してみて、見つかったのがここのやり方。
http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20040321

ここに載っているアルゴリズムのように実装してみたのだが、どうもあまりうまく動いてくれない。たぶん、自分のプログラムはSpatialオブジェクトのWorldTransformではなく、LocalTransformを操作しているのが間違いなんだと思う。しかし、WorldTransformを直接変更する方法はなく、間接的に変更する方法も調べたが結局分からなかった。

あきらめてjMEの公式サイトを漁ってみたら、そのものズバリがソース付きで載っていた。http://hub.jmonkeyengine.org/forum/topic/trackball-samples/

にゃるほどお~、lookAt関数を使うのか。lookAt関数って中身のソースを見てみたけど、全然よく分からないのよね。というかlookAt関数の元となる考え方Quanternion(四元数)自体がよくわからん。近所の本屋に扱っている本がなかったし、近所の図書館にもなかった。(中央図書館にはあるみたいだけど)

3Dではバリバリ使われているの考え方なのに、一般ではあまり需要がないのかな?まー、いずれは本腰をあげて身につけたい分野ではある。

で、今回、実装したのはこんな感じだ!

マウスモーションのイベントハンドラで、lookAtとlookUpはVector3fのメンバ変数。対象のspatialのlookAt関数の引数に使用される。sign関数は単純なもので、引数が負であれば-1、正であれば+1、ゼロであれば0を返す。sign関数を使った処理でマウスをクリックしたまま方向転換した時に変な動きにならないように補正してある。

if( mousePressed ){
int x_ = ev_.getX();
int y_ = ev_.getY();
int dx_ = mouseX0 – x_;
int dy_ = mouseY0 – y_;
float sx_ = -(float)dx_/(float)screenWidth;
float sy_ = (float)dy_/(float)screenHeight;
{
int sign0_ = sign( lastX – mouseX0 );
int sign1_ = sign( x_ – lastX );
if( sign0_ != 0 && sign1_ != sign0_ ){
mouseX0 = lastX = x_;
}
lastX = x_;
}
{
int sign0_ = sign( lastY – mouseY0 );
int sign1_ = sign( y_ – lastY );
if( sign0_ != 0 && sign1_ != sign0_ ){
mouseY0 = lastY = y_;
}
lastY = y_;
}
++debugCount;
Quaternion xq_ = new Quaternion().fromAngleAxis(
FastMath.QUARTER_PI*sx_, Vector3f.UNIT_Y
);
Quaternion yq_ = new Quaternion().fromAngleAxis(
FastMath.QUARTER_PI*sy_, Vector3f.UNIT_X
);
xq_.multLocal( lookAt );
xq_.multLocal( lookUp );
yq_.multLocal( lookAt );
yq_.multLocal( lookUp );
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です