Difference between revisions of "Rotation/ja"

From Second Life Wiki
Jump to navigation Jump to search
Line 148: Line 148:
|vector offset ||= <0, 1, 0>;||// グローバルの有効なY方向に補正値1メートルを作成します
|vector offset ||= <0, 1, 0>;||// グローバルの有効なY方向に補正値1メートルを作成します
|-
|-
|vector rotatedOffset || = offset * rot30X;||// グローバルの有効なY方向に補正値1メートルを作成します
|vector rotatedOffset || = offset * rot30X;||// rotationによって発生した動きを取得する補正値で回転します
|-
|-
|vector newPos || = {{LSLG|llGetPos}}() + rotatedOffset;||// 補正値総数で回転したプリムのポジションを移動します
|vector newPos || = {{LSLG|llGetPos}}() + rotatedOffset;||// 補正値総数で回転したプリムのポジションを移動します

Revision as of 18:08, 7 January 2008

Rotation

LSL のrotation型は3Dでの方位描写に用いられます。(型名を太字で書くように心がけています。)方位あるいは3Dアングルは四方位と呼ばれる数学的オブジェクトによって描写されます。3つが各々面を表し、4つめがオブジェクトが右か左を向いているのかを表す、4つの数字による四方位を思い浮かべることができます。四方位を用いる主な強みは、ジンバルロックの影響を受けないことです。

四方位数学の込み入った内部処理はquaternionを参照しましょう。

listの関数とイベントのrotationとの関連はRotation Synopsisを参照しましょう。

テクスチャのテクスチャの回転時に関しても情報があります。

その他の説明

rotationは<X, Y, Z>の三つの数値で表現する以外にも、オブジェクトの各角度の回転量でも表現します。これはEdit Windowで使用され、例えば人々が見たとおりに作りやすくします。これら3つの数字はvector' であってrotation ではないのですが、同じ情報として表現できるようになっています。

3番目の方法は、手前のポイント、上部のポイント、そして左側のポイントをさす、3つのvectorを用いることです。実際には3つのうち2つが必要とされ、3つめは2つから計測します。

よくある事象として、4つの数字を結合することで成り立つrotationは分かりやすいけど、初心者が理解するには難しいというものです。幸いにも実際に内部でrotatonにて表現することが必要になるのは早々無く、簡単に変換をやり取りする関数があります。

フレミングの法則

LSLの全rotationはフレミングの法則に沿っています。右手の、人差し指は有効なX軸の方向をさします。中指はY軸を さすことでしょう。親指はZ軸をさします。オブジェクトを編集するとき、三色の軸の矢印はそれぞれ有効な軸(X: red, Y: green, Z: blue) を示します。

http://en.wikipedia.org/wiki/Right_hand_rule

また、右手を動かさないまま、有効な回転方向の決定にも使います。右手を握り、親指を立てて、好きな軸の方向をさします。人差し指と中指を有効なrotationの方向に向けて曲げます。Rotationは、X、Y、Z軸と回転、傾斜角度、揺れを参照する、よくある特殊な伝達手段です。

Roll Pitch Yaw

Rotationの結合

Rotationを結合するには、掛け算割り算の演算子を用います。rotationへの足し算もしくは引き算の演算子は予期する動作にはならないので、使おうとはしないでください。掛け算の演算子は 方向の加算に、割り算の演算子は方向の引き算に応用されます。つまり、X.s = -X.sのような構成ではないということです。 float以外の型は、floatに変換されます。 non-commutativeが重要です。 rotatonへの変換はRLで重要で、理由は単純です。例えば、4つの羽のあるダーツを持っていたとして、rotation<0,0,0>の尾尻から始めて、有効なX軸方面に照準をつけ、羽をZとY軸のみにし、そしてダーツの軸とダーツ盤の軸を一直線上にします。私達はXを45度前後で、Yを30度前後回転させてやっていますが、それは間違いです。

始めに、X軸を45度回転の後にダーツはX軸上にまだあり、ぶれないまま、長時間軸にそって回転したあと、ダーツは軸を45度にするでしょう。Y軸を30度前後回転しているダーツは、X軸から30度XZ面へ降下するでしょう(rotationでのフレミングの法則は、降下移動したY軸の周囲で小さく有効に回転する、という意味だと思い出しましょう)。ダーツ風の上昇先を30度下げ、飛び始めと同じ高さを飛びますが、ダーツはそう長くは昇降せずに長時間軸に沿って回転されます。

ほかの方法を取るとするならば、最初にY軸を30度回転させて、ダーツがXZ面に回転降下するのでしょうが、X軸上にはそう長くはいないことに注目します。ダーツのX軸とダーツ板が一直線上にはならないからです。今X軸周りを45度回転するダーツは、ダーツの尾尻を中心にし、40度右上がり向きに、長時間有効なダーツ板のX軸が30度の円錐上にあるポイントへ従います。X軸へと降下しているように見えたなら、ダーツはX軸の30度以下のポイントから旋回し、右上がりにXZ面上から出て、XY面上の最初の四分儀以下のポイントへ、ダーツは回転して進みます。

明らかにこれは最初のrotationとは異なる結果ですが、rotationの結果が変えられるだけのことです。

ラジアンの構成(オイラーアングルと呼ばれる)でX、Y、Zアングルによるvectorで作成できうる値を定義する必要がある、rotation'の要素を定数のrotationにすることは、llEuler2Rot 関数にて用いるrotationに変換するということです。直に自然なrotationを代わる代わる作ることができます。実際の箇所はrotationのアングルの半分のコサインで、vectorの部分はrotationのアングルの半分のサインとrotationの標準的な角度を掛け算されたものです。llRot2Eulerを使ってrotationからオイラーアングルの vectorにしましょう。

NOTE:LSLのアングルはラジアンであって角度ではありませんが、ビルトイン定数RAD_TO_DEGDEG_TO_RADを使うことで、簡単に変換できます。X軸周りの30度のrotationのために、あなたはこう使うこともできます。

rotation rot30X = llEuler2Rot(<30, 0,0> * DEG_TO_RAD); // 角度からラジアンに変換して、vectorをrotationのrot30Xに代入します。
vector vec30X = llRot2Euler(rot30X ); // rotationからvectorへ逆変換します。(値はラジアンとなるでしょう。)

オイラーvector用のrotationの命令

上記の記述より、一つの軸以上に機能するrotationで対処するときにはっきりするのは、行われる命令が臨界ということです。この上記のオイラーの記述は、少しもっともらしい類で、3つの角度周りの単一のrotationは全体のrotationとして定義されますが、rotationは何度にすればいいのかという質問をされます。この答えはグローバル座標中のZ、Y、Xです。オイラーの描写を用いて、一回で一つの軸以上の周囲をオブジェクトが回転するように試すのなら、Z、Y、X rotationの順に用いた正しいオイラーvectorを決定して、オブジェクトに結合したrotationあるいは適用したrotationで用いるためのrotationを取得するためのllEuler2Rotを用います。

ローカル rotation vs グローバル rotation

インワールドに相対なrotationとローカルオブジェクト自身に相対なrotationとを区別することは重要です。エディタにて、お互いをいったりきたりさせることができます。スクリプトにて、望ましい振る舞いを得るために互いに変換させるべきです。

ローカルrotationは、どのようにインワールドにてオブジェクトが回転するかに関わらず、オブジェクト自身の前後、左右、上下に埋め込まれた角度の周りで行われます。グローバルrotationは、南北、東西、高低のインワールド角度周りにて行われます。プリムを編集してローカルとグローバル間で角度を変えると、どのように色づけされた角度の矢印が変わるか、プリムを回転させることで違いを見ることができます。

LSLでは、rotationをローカル'グローバルにするかの違いは、ステートメントでrotationの評価される方法によります。

このrotationは、一定の30度のrotationへオブジェクトが左向きにrotation(myRot)を開始している状態によるものがローカルの30度のrotationです。最初の例であげた最初の演算の、ダーツ自身の長軸周りをダーツが30度ひねっているものようなものです。

rotation localRot = rot30X * myRot; // 空間のrotationによる、一定のrotationtで掛け算されたローカルのrotationを行ないます。

同じrotationの値を用いてグローバルrotationをすることは、その逆の命令ということではありません。これは2つめの例の2つめの演算で、ダーツが上昇回転して、空間のX軸にそって右に回るようなものです。このケースでは、存在しているrotation(myrot)はグローバルのX軸周りを30度回転しています。

rotation globalRot = myRot * rot30X; // 一定のrotationにより、空間のrotationで掛け算されたグローバルのrotationを行ないます。

rotationの結合について他の方法を考える

左右を括弧で覆われたものを除いて、評価する命令の中で行なわれるrotationを考えることにより、このローカルグローバルの違いについて考えたくなるでしょう。

<0,0,0>から始まって発生するlocalRotのケースではrot30Xが最初に行なわれ、空間のX軸にそってプリムが回転し、回転している間は、ローカルとグローバルの角度はオブジェクトのローカルX軸に沿っての回転を行なう効果を識別します。2つめのrotationであるmyRotはプリムをオリジナルのrotationに回転させましたが、それではさらにX軸のrotationが焼きつきます。何と、これはプリムがX軸にそって回転して、YとZのrotationが変わらなかったローカルrotationのようなものです。

<0,0,0>から再び始まっているglobalRotのケースでは、最初にオブジェクトはオリジナルrotation(myrot)まで回転されますが、それではオブジェクトの角度と空間の角度は長くは調整されません。そこで、2つめのrotationであるrot30Xはローカルのケースで、オブジェクトを空間のX軸に沿って30度回転させ、確実に行ないますが、効果はオブジェクトのX軸と空間のX軸が今回一致しなくなってから、空間のX軸にそった円錐体をとおしてオブジェクトを回転することです。なんと、これはプリムが空間のX軸にそって30度旋回したもので、ゆえにグローバルrotationのようなものです。

rotationの割り算は、反対の方向のrotationにする効果があり、330度のrotationによる掛け算は、30度のrotationによる割り算と同じです。

rotationを使う

R.x、R.y、R.z、 そしてR.s(R.wではありません)によるrotationRの特定の構成でアクセスが可能です。スカラー部R.sはrotationのアングルの半分のコサインです。vector部(R.x、R.y、R.z)はrotationの一般的な角度とrotationのアングルの半分のサインの積です。x、y、zが無効になることによる(あるいは無効な値をつくることにより)、逆のrotationを生成可能です。余談ですが、float 値のリポジトリとしてrotationを使うことも可能で、各rotationは4つのfloat 値を貯蓄し、rotationから成り立つlistfloatの集まりから成り立つlistよりもさらに効率的ですが、それの中身を覗くのはコストが高いでしょう。

rotation rot30X = llEuler2Rot(<30, 0,0> * DEG_TO_RAD ); // rotation定数を作成する
rotation rotCopy = rot30X; // rotCopyに全4つのfloatの構成をコピーします
float X = rotCopy.x; // rotationの特定の構成を出力します
float Y = rotCopy.y;
float Z = rotCopy.z;
float S = rotCopy.s;
rotation anotherCopy = <X, Y, Z, S>; // 構成から他のrotationを作ります


直接、あるいはrotation Rを反転する必要があるならば、RによってZERO_ROTATIONを分割して使うことが出来る、zero rotationのビルトイン定数があります。上記の注意として、最初のzero potitionの回転による作業は 次にそれを分割させるため、オリジナルのrotationの逆向きに回転させ、その結果反転のrotationにします。

rotation rot330X = <-rot30X.x, -rot30X.y, -rot30X.z, rot30X.s>; // rotationの反転 - この構成は有効ではありません
rotation another330X = ZERO_ROTATION / rot30X; // 割り算によるrotationの反転で、rot330Xと結果は同じです
rotation yetanother330X = <rot30X.x, rot30X.y, rot30X.z, -rot30X.s>; // まったくの同じものではありませんが、同じ働きをします

単一もしくはルートプリム vs リンクプリム vs アタッチメント

単一かリンクプリムのrotationについて話す理由は乗り物のドラのようなもののためで、期待された動作は、たとえ乗り物全体のrotationに何があろうとも、乗り物と相対的にドアが動くことです。可能な限りこれをグローバルrotationにする間は、手をつけることすらないでしょう。 プリムには独自で、linksetの一部、attachmentの一部があり、一般的な3つの等位なシステムがあります。プリムが独立しているとき、たとえばlinksetの一部ではなく、ルーとプリムのように動いたり、attachmentの一部のときは、ちょっと壊れたような異なる動きをします。

Getting and setting rotations of prims
Function Ground (rez'ed) Prims Attached Prims
Root Children Root Children
llGetRot
llGPP:PRIM_ROTATION
llGetObjectDetails
global rotation of prim global rotation of prim global rotation of avatar global rotation of avatar * global rotation of prim (Not Useful)
llGetLocalRot
llGPP:PRIM_ROT_LOCAL
global rotation of prim rotation of prim relative to root prim rotation of attachment relative to attach point rotation of prim relative to root prim
llGetRootRotation global rotation of prim global rotation of root prim global rotation of avatar global rotation of avatar
llSetRot*
llSPP:PRIM_ROTATION*
set global rotation complicated, see llSetRot set rotation relative to attach point set rotation to root attachment rotation * new_rot.
llSetLocalRot*
llSPP:PRIM_ROT_LOCAL*
set global rotation set rotation of prim relative to root prim set rotation relative to attach point set rotation of prim relative to root prim
llTargetOmega
ll[GS]PP:PRIM_OMEGA
spin linkset around prim's location spin prim around its location spin linkset around attach point spin prim around its location
Physical objects which are not children in a linkset will not respond to setting rotations.
†  For non-Physical objects llTargetOmega is executed on the client side, providing a simple low lag method to do smooth continuous rotation.

Vectorの回転

LSLで、rotationの中心がオブジェクトの中心はないときに輪や弧の中でオブジェクトを動かしたいのなら、vectorの回転はとても使い勝手がよいです。

とても整っていますが、目で見るものは殆どありません。上記のダーツの回転の議論を思い出しして、物理のダーツとvectorを、基点をダーツの尾尻、そしてX、Y、Zの構成ダーツの頂点のポジションと記述して、置き換えてみましょう。ダーツの尾尻にそって回転しているダーツは全体の頂点が移動し、rotationの中心はダーツの尾尻の弧です。まったく同じものは プリムの中心から同じ弧を通してプリムが回転する補正値を描写する、回転しているvectorです。なんと、これはオブジェクトがプリムの中心からのvector位置補正値周辺を回転するかのようにみえます。

rotation rot30X = llEuler2Rot(<30, 0,0> * DEG_TO_RAD ); // X軸周りの30度のrotationの定数を作成します
vector offset = <0, 1, 0>; // グローバルの有効なY方向に補正値1メートルを作成します
vector rotatedOffset = offset * rot30X; // rotationによって発生した動きを取得する補正値で回転します
vector newPos = llGetPos() + rotatedOffset; // 補正値総数で回転したプリムのポジションを移動します

Nota Bene: これによっておこなう移動は、10mもしくはそれ以下の地下に埋まっているオフワールドのプリムが移動する問題について忘れてはいけません。

定数

ZERO_ROTATION

ZERO_ROTATION = <0.0, 0.0, 0.0, 1.0>;
このrotation定数は<0.0, 0.0, 0.0>のオイラーアングルの代数です。

DEG_TO_RAD

DEG_TO_RAD = 0.01745329238f;
DEGREES(角度)のアングルをラジアンのアングルに渡して乗算するときのfloat定数です。

RAD_TO_DEG

RAD_TO_DEG = 57.29578f;
ラジアンのアングルをDEGREES(角度)のアングルに渡して乗算するときのfloat定数です。