Difference between revisions of "Rotation/ja"

From Second Life Wiki
Jump to navigation Jump to search
m
Line 51: Line 51:
</div></div>
</div></div>


==オイラーvector用のrotationの命令==
==オイラーベクトルでの回転の順番==


上記の記述より、一つの軸以上に機能するrotationで対処するときにはっきりするのは、行われる命令が臨界ということです。この上記の'''オイラー'''の記述は、少しもっともらしい類で、3つの角度周りの単一のrotationは全体の''rotation''として定義されますが、rotationは何度にすればいいのかという質問をされます。この答えはグローバル座標中の'''Z、Y、X'''です。''オイラー''の描写を用いて、一回で一つの軸以上の周囲をオブジェクトが回転するように試すのなら、Z、Y、X rotationの順に用いた正しいオイラー{{LSLG/ja|vector|vector}}を決定して、オブジェクトに結合したrotationあるいは適用したrotationで用いるための'''rotation'''を取得するための{{LSLG/ja|llEuler2Rot|llEuler2Rot}}を用います。
上述の議論より1つ以上の軸で回転する場合、それらの回転する順番が重要となるのは明らかです。''オイラー''の議論ではこれはちょっと少しごまかしました。3つの軸周りの個々の回転は総合的な''回転''を定義します。しかし、それでは疑問が浮かびます: どんな軸の順番で回転しているのか? その答えはグローバル座標系では'''Z,Y,Z'''です。オブジェクトを''オイラー''表現を用いて1つ以上の軸で同時に回転させたい場合、現在の''オイラー''{{LSLG/ja|vector|vector}}をZ, Y, X回転の順に決定し、回転の合成またはオブジェクトへ回転を適用させるための'''rotation'''を得るために{{LSLG/ja|llEuler2Rot|llEuler2Rot}}関数を使います。


==ローカル rotation vs グローバル rotation==
==ローカル vs グローバル(ワールド)rotation==


インワールドに相対な'''rotation'''とローカルオブジェクト自身に相対な'''rotation'''とを区別することは重要です。エディタにて、お互いをいったりきたりさせることができます。スクリプトにて、望ましい振る舞いを得るために互いに変換させるべきです。
ワールドの'''rotation'''とオブジェクト自体のローカルの'''rotation'''とを区別することは重要です。エディタでは、あなたは一方からもう片方へと切り替えることができます。 スクリプトではあなたは要求する振る舞いを得るために一方から他方へと変換しなければなりません。


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


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


このrotationは、一定の30度の'''rotation'''へオブジェクトが左向きに''rotation'''(myRot)を開始している状態によるものが''ローカル'''の30度のrotationです。最初の例であげた最初の演算の、ダーツ自身の長軸周りをダーツが30度ひねっているものようなものです。
これは、30度の一定の'''rotation'''をオブジェクトの最初の'''rotation'''(myRot)の左側につけることで'''ローカル'''での30度の回転を行います。それは上述のダーツをその長軸の周りに30度にねじる最初の例の最初の操作に似ています。


<div id="box"><div style="padding: 0.5em">
<div id="box"><div style="padding: 0.5em">
{| cellpadding=0 cellspacing=0
{| cellpadding=0 cellspacing=0
|-
|-
|rotation localRot = ||rot30X * myRot;||// 空間のrotationによる、一定のrotationtで掛け算されたローカルのrotationを行ないます。
|rotation localRot = ||rot30X * myRot;||// ワールドの回転に一定の回転をかけることでローカルの回転を行う。
|}
|}
</div></div>
</div></div>


同じ'''rotation'''の値を用いて'''グローバル'''rotationをすることは、その逆の命令ということではありません。これは2つめの例の2つめの演算で、ダーツが上昇回転して、空間のX軸にそって右に回るようなものです。このケースでは、存在しているrotation(myrot)はグローバルのX軸周りを30度回転しています。
'''グローバル'''の回転をするためには同じ'''rotation'''を使いますが、順番は逆にしてください。これはダーツが上昇回転してワールドのX軸周りに右に回る2番目の例の2番目の操作に似ています。この場合、既存のrotation(myRot)はグローバルのX軸の周りで30度回転します。


<div id="box"><div style="padding: 0.5em">
<div id="box"><div style="padding: 0.5em">
{| cellpadding=0 cellspacing=0
{| cellpadding=0 cellspacing=0
|-
|-
|rotation globalRot || = myRot * rot30X;||// 一定のrotationにより、空間のrotationで掛け算されたグローバルのrotationを行ないます。
|rotation globalRot || = myRot * rot30X;||// 一定の回転をワールドの回転にかけることでグローバルの回転を行う。
|}
|}
</div></div>
</div></div>

Revision as of 10:51, 22 February 2008

Rotation

LSL のrotation型は3Dでの方位を表すのに用いられます。(型名を太字で書くように心がけています。)方位あるいは3Dアングルは四元数と呼ばれる数学的オブジェクトによって表されます。四元数は4つの数値から成ると考えることができ、3つがオブジェクトの向いている方向を表し、4つめがその方向の周りでのオブジェクトの右か左への傾きを表します。四元数を用いる主な利点は、ジンバルロックの影響を受けないことです。

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

rotationに関連する関数とイベントの一覧はRotation Synopsisを参照しましょう。

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

その他の表現

回転を表す他の手段は、<X,Y,Z>の3つからなる数値を、オブジェクトの各軸回りの回転量(ラジアン)として用いることです。これは例えばエディットウィンドウで用いられていて、人々が思い描くのがわりと容易です。この3つの数値はvectorであってrotation型では無いことに注意してください。ですがそれらは同じ情報を表すことができます。これは回転のオイラー角表現と呼ばれます。

3番目の方法は、前方、上方、そして左側を指す3つのvectorを用いることです。実際には3つのうち2つのみが必要で、3つめの値は2つから求めます。

回転を合成できるなどのもっともな理由があるので、4つの数値からなるrotationは優れているのですが、初心者が理解するのはより難しいです。幸いにも、実際のrotationの内部表現で何かすることはめったに必要ありませんし、また簡単にこれらの間を変換する関数があります。

右手ルール

LSLでは全ての回転が右手ルールに沿って行われています。右手で人差し指をx軸の正方向へ伸ばしてみてください。中指を人差し指から直角に伸ばすと、y軸の正方向を指します。そして親指を両指から直角に伸ばすとz軸の正方向を指します。あなたがオブジェクトを編集するとき、3色の軸の矢印は各軸(X: 赤, Y: 緑, Z: 青)の正方向を示します。

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

さて、右手はまだ戻さないでください。正方向の回転の向きを求めるという別の使い道があります。右手を握り、親指を立てて好きな軸の正方向を指します。あなたの他の指は正方向の回転の向きに曲がります。x,y,z軸周りの回転は特に乗り物において、しばしばロール、ピッチ、ヨーとして示されます。

Roll Pitch Yaw

Rotationの合成

Rotationを合成するには、掛け算割り算の演算子を用います。rotationへの足し算もしくは引き算の演算子は予期する動作にはならないので、使おうとはしないでください。掛け算の演算子は 正方向の回転に、割り算の演算子は負方向の回転に用いられます。X.s = -X.sのようにして成分sを直接反転させて回転を反転させることもできます。 他のfloatのような型と異なり、計算の順番(非可換)は重要です。 その理由は簡単です:回転させる順番はRLにおいても重要です。例えば、あなたが4枚の羽根のついたダーツを持っていたとして、その尾部を原点とし、狙う方向を正のX方向としてX軸上に置き、羽根をZ軸とY軸上に沿わせて、ダーツの軸とその軸が一直線に並んだ状態を回転<0, 0, 0>とします。これをX軸回りに45度、Y軸周りに30度、異なった順番で回転させてみます。

まずX軸回りに45度回転させた後ではダーツはまだX軸方向を向いていて動いていない。羽根は45度、その軸で回転する。次に、Y軸回りの30度回転はXZ平面上でX軸から30度の方向にダーツを動かす。(回転の右手ルールが、Y回りの正方向への小さな回転は位置を下げることを意味するのを覚えていてください)ダーツは回り始めたのと同じ垂直面上で30度下がることになる。しかし、それ自身の長い軸で回るので羽根はもう上下しません。

別のやり方として最初にY軸周りに30度回転するとダーツはXZ平面上で回転しますが、X軸上にはダーツがもう無いのに注目してください。そのX軸と空間上のX軸はもう並ぶことはありません。今、X軸での45度回転はダーツの先端をX軸の正領域に沿った軸による30度の円錐に合わせて、その尾部で45度右斜め上へ旋回させる。あなたがX軸から見下ろしていると、それはX軸の下から30度の位置から右斜め上へ、XZ平面の外でXY平面の第一象限の下の位置へ回転するようにダーツの羽根は旋回します。

これは明らかに最初の回転とは異なった結果ですが、回転の順番だけが変化しただけです。

一定の回転を行うために、ラジアンでX,Y,Zの角度を要素とするvector(オイラー角と呼ばれる)を作成し、llEuler2Rot関数を使ってそれをrotationに変換してrotation値を定義する必要があります。あなたは回転を直接作成することもできます。実数部は回転角の1/2のcosです。ベクトルの部分は正規化した回転軸に回転角の1/2のsinを掛けたものです。 rotationからvectorのオイラー角回転へはllRot2Eulerを使います。

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へ逆変換します。(値はラジアンとなるでしょう。)

オイラーベクトルでの回転の順番

上述の議論より1つ以上の軸で回転する場合、それらの回転する順番が重要となるのは明らかです。オイラーの議論ではこれはちょっと少しごまかしました。3つの軸周りの個々の回転は総合的な回転を定義します。しかし、それでは疑問が浮かびます: どんな軸の順番で回転しているのか? その答えはグローバル座標系ではZ,Y,Zです。オブジェクトをオイラー表現を用いて1つ以上の軸で同時に回転させたい場合、現在のオイラーvectorをZ, Y, X回転の順に決定し、回転の合成またはオブジェクトへ回転を適用させるためのrotationを得るためにllEuler2Rot関数を使います。

ローカル vs グローバル(ワールド)rotation

ワールドのrotationとオブジェクト自体のローカルのrotationとを区別することは重要です。エディタでは、あなたは一方からもう片方へと切り替えることができます。 スクリプトではあなたは要求する振る舞いを得るために一方から他方へと変換しなければなりません。

ローカルの回転は、オブジェクトがワールド内でどんな回転をしているかに関わらないオブジェクト自身の前後、左右、上下に当てはめられた軸周りでの回転です。グローバルの回転は南北、東西、上下のワールドの軸周りでの回転です。あなたはプリムの回転の違いを見ることができ、編集やローカルとグローバルの軸の設定を色のついた矢印が変わるの注意しながら変更することができます。

LSLではローカルグローバルの回転の違いは、ステートメント内でrotationが評価される順番の違いとなります。

これは、30度の一定のrotationをオブジェクトの最初のrotation(myRot)の左側につけることでローカルでの30度の回転を行います。それは上述のダーツをその長軸の周りに30度にねじる最初の例の最初の操作に似ています。

rotation localRot = rot30X * myRot; // ワールドの回転に一定の回転をかけることでローカルの回転を行う。

グローバルの回転をするためには同じrotationを使いますが、順番は逆にしてください。これはダーツが上昇回転してワールドのX軸周りに右に回る2番目の例の2番目の操作に似ています。この場合、既存のrotation(myRot)はグローバルのX軸の周りで30度回転します。

rotation globalRot = myRot * rot30X; // 一定の回転をワールドの回転にかけることでグローバルの回転を行う。

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
関数 地面の (rez'ed) プリム アタッチメント プリム
単一かルート リンクメンバ 単一かルート リンクメンバ
llGetRot
llGPP:PRIM_ROTATION
llGetObjectDetails
プリムのグローバルrotation プリムのグローバルrotation アバタのグローバルrotation アバタのグローバルrotation * プリムのグローバルrotation(使い勝手はよくありません)
llGetLocalRot
llGPP:PRIM_ROT_LOCAL/ja
プリムのグローバルrotation プリムのrotationと相対的なルートプリム アタッチメントのrotationと相対的なアタッチポイント ルートプロムのアタッチメントと相対的なプリムのrotation
llGetRootRotation プリムのグローバルrotation ルートプリムのグローバルrotation アバタのグローバルrotation アバタのグローバルrotation
llSetRot*
llSPP:PRIM_ROTATION*
グローバルrotationを設定します 複雑です。llSetRotを参照します アバタと相対的なrotationを設定します ルートグローバルrotation* new_rotのrotationを設定します
llSetLocalRot*
llSPP:PRIM_ROT_LOCAL*
グローバルrotationを設定します ルートプリムと相対的なプリムのrotationを設定します アバターの相対的なグローバルrotationを設定します アタッチメントのルートプリムと相対的なプリムのrotationを設定します
llTargetOmega
ll[GS]PP:PRIM_OMEGA
プリムの中心周りをリンクされた全体が回転します プリムの中心周りをプリムが回転します アタッチメントの中心周りをリンクされた全体が回転します アタッチメントの中心周りをプリムが回転します
はリンクされた全体のうちの子プリムではない物理的オブジェクト はrotationの設定が反応しないでしょう。
†  物理的オブジェクトではないもののために、 llTargetOmega はもしスムースな連続回転する方法を行なうならば、クライアントサイドで実行されます。

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定数です。