note.x

[Papervision3D2.0] Quaternion

前回作った、マウスのクリック位置に応じてオブジェクトが移動するデモを応用して、平面上じゃなく球面上をオブジェクトが移動するものを作ってみた。ヨユーで出来たみたいな物言いだけど、オレには難易度高すぎな課題だった…orz。

e_quaternion.jpg

InteractiveFacelevelTest3.swf(要:FlashPlayer9)

平面上を移動させたい場合は、変化する座標が2軸だけなので2Dと同じ感覚で処理すれば、まぁ問題無い感じで動く。球面上を移動させたい場合は、この考え方で実装すると始点と終点の角度が大きくなるにつれ、移動するオブジェクトが球体にメリ込んじゃう。

失敗例(要:FlashPlayer9)

Tweenerのベジェ補間とかを上手く使えばソレっぽいものが出来そうな気もしたんだけど、いい加減3Dプログラミングにおける数学的知識も蓄えていかないといかんなぁと思って、クォータニオンで座標変換することに挑戦してみた。はっきり言って自分でも全く理解できてないので備忘録としてメモっとく。

PV3D2.0には core.math.Quaternion っていうクラスが用意されてるのでこれを使った。Matrix3DにもQuaternionを扱えるメソッドがあるけど、core.math.Quaternionには、SLERP (Spherical Linear intERPolation 球面線形補間)のためのメソッドがあるし、せっかくなのでこっちで。

位置の移動については以下のようなことをした。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//回転させたい点の初期位置(始点)のクォータニオン生成
var qStart:Quaternion = new Quaternion(obj.x,obj.y,obj.z,0);
 
//マウスクリック位置(終点)のベクトル
var clickVec:Number3D = new Number3D(click.x,click.y,click.z);
 
//始点と終点(マウスをクリックした座標)のベクトルの外積から法線ベクトル(回転軸)生成
var startVec:Number3D = new Number3D(obj.x, obj.y, obj.z);
startVec.normalize();
clickVec.normalize();
var vcross:Number3D = Number3D.cross(startVec,clickVec);
 
//始点と終点のベクトルの内積から回転角度(ラジアン)生成
var rot:Number = Math.acos(Number3D.dot(startVec,clickVec));
 
//指定軸回りの回転クォータニオンqを生成
var q:Quaternion = Quaternion.createFromAxisAngle(vcross.x,vcross.y,vcross.z,rot);
 
//qの共役クォータニオン(ベクトル部の符号が反転したもの)rを算出
var r:Quaternion = Quaternion.conjugate(q);
 
//r・qStart(始点)・qと掛け算回転後のクォータニオンを生成
var ans:Quaternion = Quaternion.multiply(r,qStart);
ans = Quaternion.multiply(ans,q);
 
//クォータニオンから行列に変換
var m:Matrix3D = Matrix3D.translationMatrix(ans.x,ans.y,ans.z);
 
//行列を適用
obj.copyTransform(m);

上のコードをそのまま実装すると、クリック直後にオブジェクトがワープするので実際には回転クォータニオンを生成する際の角度の値を時間経過にしたがって変化させる。

クォータニオンをどう扱うのかについては、IKDさんの「マルペケつくろーどっとコム」内の、
クォータニオンを学んでみよう!
クォータニオンを学んで見よう:サンプルプログラム
が大変参考になりました。始点のクォータニオンと回転クォータニオンから、終点クォータニオンを得るあたりは完全に丸写し;

オブジェクト自身の姿勢制御については、以下のように

//最初の姿勢クォータニオン生成
var pos1:Quaternion = Quaternion.createFromOrthoMatrix(obj.transform);
//最終的な姿勢クォータニオン生成
var pos2:Quaternion = Quaternion.createFromOrthoMatrix(marker.transform);
pos1.normalize();
pos2.normalize();

//球面線形補間(slerp)を使ってオブジェクトの姿勢を補間(t = 0〜1)
var gpos:Quaternion = Quaternion.slerp( pos1, pos2, t );
gpos.normalize();

slerpメソッドを使うことで2つのクォータニオンから時間tにおけるクォータニオンが得られるらしい。とにかく初期状態と変化後のクォータニオン作って、tを0から1に変化させれば、中間の状態が取れるということで自分を納得させた(笑)このクォータニオンを行列に変換して、前述した移動のための行列とかけ算すれば(Matrix3D.multiply(m,gpos);)移動しつつ姿勢が変化していく行列が得られると。

あと、slerpを使う場合、初期値のクォータニオンと変化後のクォータニオンの内積が0以上じゃないと、遠回りな補間しちゃうので、この条件に該当する場合は初期値のクォータニオンのベクトル部の符号を反転させるという、かなり素人考えな方法で対処した;きっといい方法があるんだろうなぁ。

出来上がったものは微妙に挙動がおかしいし、ときどきオブジェクトがとんでもない座標に移動しちゃったりするし、クォータニオンって結局何なのよって感じだけど概ねイメージ通りのものができた。ベクトルも行列もクォータニオンも理論はサッパリだけど、道具としての扱い方は解ってきたので、ようやく3Dプログラミングの入り口付近にたどり着けたのかなと。


TRACKBACK

  1. タロタローグ ブログ - 2008.03.03 0:58:32

    Metasequoia.asをインタラクティブにする方法:詳…

    さて、とりあえずMetasequoia.asをインタラクティブ化するために必要な修正はわかったので、それを実現するためのコードを掲載。といっても、前回のコード断片でほぼ (more…)

  2. 水玉製作所 » [PV3D]QbicQube - 2009.07.19 16:55:04

    [...] 参考 http://blog.r3c7.net/?p=152 http://yamasv.blog92.fc2.com/blog-entry-139.html http://yamasv.blog92.fc2.com/blog-entry-135.html [...]

  3. [...] note.x | [Papervision3D2.0] Quaternion blog.r3c7.net/?p=152 – view page – cached nには、SLERP (Spherical Linear intERPolation 球面線形補間)のためのメソッドがあるし、せっかくなのでこっちで。 F [...]

  4. [...] http://blog.r3c7.net/?p=152 小日本的治学精神,令人佩服,学习了! 分享这篇文章! [...]

Trackback URL : http://blog.r3c7.net/as3-software-rendering/152/trackback/

COMMENTS

  1. Tim - 2008.02.12 22:43:14

    Hello :)
    Your work is great!
    PLEASE PLEASE could you send me the FLA?
    Let us swap FLA
    THANK YOU

  2. Freddy - 2008.02.14 19:29:14

    Yeah!! really great job… source please :-)

  3. kazuki0413 - 2008.02.17 12:47:52

    お初になります。私もPapervision3Dを使っていて
    いつも参考にさせてもらっています!
    自分もちゃんと数学的な事から勉強し直さなきゃなぁと
    思っていたので今回もとても参考になりました。
    その前にPV3D1.7から2.0に乗り換えなきゃ…

  4. kalle - 2008.02.23 13:53:50

    おーい、
    ニースの仕事!
    私を学びたい quaternion 。
    私には分からないのアニメーション(トゥイナー ?) 。
    これをどうやって行うか?アドバイスを教えてもらえますか?またはtippですか?

    http://kallesaas.com/pv3d/quaternion/spherenavigation/spherequarternion.swf
    http://kallesaas.com/pv3d/quaternion/spherenavigation/spherequarternion.as

    ありがとうございます。

    (申し訳ありませんが私のために日本: http://www.google.de/translate_t ; )

Leave a Reply