Difference between revisions of "Rotation/ja"

From Second Life Wiki
Jump to navigation Jump to search
m
Line 26: Line 26:
[http://en.wikipedia.org/wiki/Tait-Bryan_angles Roll Pitch Yaw]
[http://en.wikipedia.org/wiki/Tait-Bryan_angles Roll Pitch Yaw]


==Rotationの結合==
==Rotationの合成==
'''Rotation'''を結合するには、'''掛け算'''と'''割り算'''の演算子を用います。'''rotation'''への足し算もしくは引き算の演算子は予期する動作にはならないので、使おうとはしないでください。'''掛け算'''の演算子は
'''Rotation'''を合成するには、'''掛け算'''と'''割り算'''の演算子を用います。'''rotation'''への足し算もしくは引き算の演算子は予期する動作にはならないので、使おうとはしないでください。'''掛け算'''の演算子は
方向の加算に、'''割り算'''の演算子は方向の引き算に応用されます。つまり、X.s = -X.sのような構成ではないということです。
正方向の回転に、'''割り算'''の演算子は負方向の回転に用いられます。X.s = -X.sのようにして成分sを直接反転させて回転を反転させることもできます。
{{LSLG|float/ja|float}}以外の型は、floatに変換されます。
他の{{LSLG|float/ja|float}}のような型と異なり、計算の順番([http://ja.wikipedia.org/wiki/%E4%BA%A4%E6%8F%9B%E6%B3%95%E5%89%87 非可換])は重要です。
[http://en.wikipedia.org/wiki/Commutative non-commutative]が重要です。
その理由は簡単です:回転させる順番はRLにおいても重要です。例えば、あなたが4枚の羽根のついたダーツを持っていたとして、その尾部を原点とし、狙う方向を正のX方向としてX軸上に置き、羽根をZ軸とY軸上に沿わせて、ダーツの軸とその軸が一直線に並んだ状態を回転<0, 0, 0>とします。これをX軸回りに45度、Y軸周りに30度、異なった順番で回転させてみます。
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度下げ、飛び始めと同じ高さを飛びますが、ダーツはそう長くは昇降せずに長時間軸に沿って回転されます。
まずX軸回りに45度回転させた後ではダーツはまだX軸方向を向いていて動いていない。羽根は45度、その軸で回転する。次に、Y軸回りの30度回転はXZ平面上でX軸から30度の方向にダーツを動かす。(回転の右手ルールが、Y回りの正方向への小さな回転は位置を下げることを意味するのを覚えていてください)ダーツは回り始めたのと同じ垂直面上で30度下がることになる。しかし、それ自身の長い軸で回るので羽根はもう上下しません。


ほかの方法を取るとするならば、最初にY軸を30度回転させて、ダーツがXZ面に回転降下するのでしょうが、X軸上にはそう長くはいないことに注目します。ダーツのX軸とダーツ板が一直線上にはならないからです。今X軸周りを45度回転するダーツは、ダーツの尾尻を中心にし、40度右上がり向きに、長時間有効なダーツ板のX軸が30度の円錐上にあるポイントへ従います。X軸へと降下しているように見えたなら、ダーツはX軸の30度以下のポイントから旋回し、右上がりにXZ面上から出て、XY面上の最初の四分儀以下のポイントへ、ダーツは回転して進みます。
別のやり方として最初にY軸周りに30度回転するとダーツはXZ平面上で回転しますが、X軸上にはダーツがもう無いのに注目してください。そのX軸と空間上のX軸はもう並ぶことはありません。今、X軸での45度回転はダーツの先端をX軸の正領域に沿った軸による30度の円錐に合わせて、その尾部で45度右斜め上へ旋回させる。あなたがX軸から見下ろしていると、それはX軸の下から30度の位置から右斜め上へ、XZ平面の外でXY平面の第一象限の下の位置へ回転するようにダーツの羽根は旋回します。


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


ラジアンの構成(オイラーアングルと呼ばれる)でX、Y、Zアングルによる{{LSLG|vector}}で作成できうる値を定義する必要がある、''rotation'''の要素を定数のrotationにすることは、{{LSLG|llEuler2Rot/ja|llEuler2Rot}} 関数にて用いる'''rotation'''に変換するということです。直に自然なrotationを代わる代わる作ることができます。実際の箇所はrotationのアングルの半分のコサインで、vectorの部分はrotationのアングルの半分のサインとrotationの標準的な角度を掛け算されたものです。{{LSLG|llRot2Euler/ja|llRot2Euler}}を使ってrotationからオイラーアングルの {{LSLG|vector/ja|vector}}にしましょう。
一定の回転を行うために、ラジアンでX,Y,Zの角度を要素とする{{LSLG|vector}}(オイラー角と呼ばれる)を作成し、{{LSLG|llEuler2Rot/ja|llEuler2Rot}}関数を使ってそれを'''rotation'''に変換して'''rotation'''値を定義する必要があります。あなたは回転を直接作成することもできます。実数部は回転角の1/2のcosです。ベクトルの部分は正規化した回転軸に回転角の1/2のsinを掛けたものです。
 
rotationから{{LSLG|vector/ja|vector}}のオイラー角回転へは{{LSLG|llRot2Euler/ja|llRot2Euler}}を使います。
'''NOTE:'''LSLのアングルはラジアンであって角度ではありませんが、ビルトイン定数[[#RAD_TO_DEG|RAD_TO_DEG]] と [[#DEG_TO_RAD|DEG_TO_RAD]]を使うことで、簡単に変換できます。X軸周りの30度の'''rotation'''のために、あなたはこう使うこともできます。


'''NOTE:'''LSLでの角度はラジアンであって度ではありませんが、組み込み定数[[#RAD_TO_DEG|RAD_TO_DEG]] と [[#DEG_TO_RAD|DEG_TO_RAD]]を使うことで簡単に変換できます。X軸周りの30度の'''rotation'''に対して以下のように使うこともできます:
<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 rot30X ||= {{LSLG|llEuler2Rot}}(<30, 0,0> * DEG_TO_RAD);||// 角度からラジアンに変換して、{{LSLG|vector/ja|vector}}をrotationのrot30Xに代入します。
|rotation rot30X ||= {{LSLG|llEuler2Rot}}(<30, 0,0> * DEG_TO_RAD);||// 度をラジアンに変換してから、{{LSLG|vector/ja|vector}}をrotationのrot30xに代入します。
|-
|-
|{{LSLG|vector}} vec30X ||= {{LSLG|llRot2Euler}}(rot30X );||// rotationから{{LSLG|vector/ja|vector}}へ逆変換します。(値はラジアンとなるでしょう。)
|{{LSLG|vector}} vec30X ||= {{LSLG|llRot2Euler}}(rot30X );||// rotationから{{LSLG|vector/ja|vector}}へ逆変換します。(値はラジアンとなるでしょう。)

Revision as of 18:15, 19 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へ逆変換します。(値はラジアンとなるでしょう。)

オイラー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
関数 地面の (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定数です。