Difference between revisions of "Rotation/ja"

From Second Life Wiki
Jump to navigation Jump to search
 
(16 intermediate revisions by 7 users not shown)
Line 1: Line 1:
{{Multi-lang}}
{{Multi-lang}}
{{LSL Header/ja}}{{RightToc}}
{{LSL Header/ja}}{{RightToc}}
=Rotation=
==Rotation==
LSL の'''rotation'''型は3Dでの方位を表すのに用いられます。(型名を'''太字'''で書くように心がけています。)方位あるいは3Dアングルは{{LSLG|quaternion/ja|四元数}}と呼ばれる数学的オブジェクトによって表されます。四元数は4つの数値から成ると考えることができ、3つがオブジェクトの向いている方向を表し、4つめがその方向の周りでのオブジェクトの右か左への傾きを表します。四元数を用いる主な利点は、[http://en.wikipedia.org/wiki/Gimbal_Lock ジンバルロック]の影響を受けないことです。
[[rotation/ja|回転]] は 4つの[[float/ja|浮動小数点値]] を含む{{LSLGC|Types|データ型}}です。


四元数数学の込み入った内部処理は{{LSLG|quaternion/ja|quaternion}}を参照しましょう。
各要素は、変数名に <code>.x</code>、<code>.y</code>、<code>.z</code>、または <code>.s</code> を追加することで個別にアクセスできます。
<source lang="lsl2">rotation rot;
float x = rot.x;
float y = rot.y;
float z = rot.z;
float s = rot.s;</source>


rotationに関連する関数とイベントの一覧は{{LSLG|Rotation Synopsis/ja|Rotation Synopsis}}を参照しましょう。
LSL の'''rotation'''型は3Dでの方位を表すのに用いられます。(型名を'''太字'''で書くように心がけています。)方位あるいは3Dアングルは{{LSLG/ja|quaternion|クォータニオン}}と呼ばれる数学的オブジェクトによって表されます。クォータニオンは4つの数値から成ると考えることができ、3つがオブジェクトの向いている方向を表し、4つめがその方向の周りでのオブジェクトの右か左への傾きを表します。クォータニオンを用いる主な利点は、[http://en.wikipedia.org/wiki/Gimbal_Lock ジンバルロック]の影響を受けないことです。
クォータニオン数学の込み入った内部処理は{{LSLG/ja|quaternion|クォータニオン}}を参照してください。
rotationに関連する関数とイベントの一覧は{{LSLG/ja|Rotation Synopsis|Rotation Synopsis}}を参照してください。
{{LSLG/ja|texture|テクスチャ}}の項にテクスチャの回転に関しての情報があります。


{{LSLG|texture/ja|テクスチャ}}のテクスチャの回転時に関しても情報があります。
回転はしばしば非常に混乱するトピックと見なされ、スクリプターは試行錯誤して正確な結果を得ることがあります。この混乱の理由は次のとおりです:
* 誰もが本当の意味で[[quaternion/ja|クォータニオン]] が何であり、それをどのように考えるべきかを正確に知らない(完全には真実ではありませんが、脳は4つの幾何学的次元で考えることが得意ではありません)。
* 実際には異なるタイプのベクトル('dir'、'vec'、'pos')がいくつかあり、それぞれ異なる方法で操作する必要があります。
* 移動と回転を適用する順序はケースによって異なる場合があります。
* 適用された回転と座標系間の回転 'オフセット' の違いについて混乱があります。
したがって、回転をマスターするには、変数のための良い命名システムを使用することが不可欠です。このようなシステムは、[[User:Timmy_Foxclaw/About_Coordinate_Systems_and_Rotations|About Coordinate Systems and Rotations]] で [[User:Timmy_Foxclaw|Timmy Foxclaw]]によって詳しく説明されています。


==その他の説明==
==その他の表現==
rotationは<X, Y, Z>の三つの数値で表現する以外にも、オブジェクトの各角度の回転量でも表現します。これはEdit Windowで使用され、例えば人々が見たとおりに作りやすくします。これら3つの数字は''vector''' であって'''rotation''' ではないのですが、同じ情報として表現できるようになっています。
===Euler vector===
3D角度を表す別の方法は、<X、Y、Z> という3つの数値を使用することです。これらの数値は、オブジェクトが各軸を中心に回転する量を表します。たとえば、これは編集ウィンドウで使用され、一般的には人々が視覚化しやすいです。編集ウィンドウでの回転 <x、y、z> 数値を調整し、オブジェクトの挙動を確認するのは簡単です。編集ウィンドウでは、数値は度数で表されます。つまり、直角は90度です。


3番目の方法は、手前のポイント、上部のポイント、そして左側のポイントをさす、3つのvectorを用いることです。実際には3つのうち2つが必要とされ、3つめは2つから計測します。
LSLでは、これらの3つの角度は度数ではなく{{LSLG/ja|radians|ラジアン}}で表されます。つまり、直角はPI/2です。ラジアンは非常に幅広い度数のようなものです。
これらの3つの数値は、回転型ではなくベクトル型であり、同じ情報を表すことができます。これは3D角度の ''オイラー'' 表現と呼ばれます。'''LSLでは、zの周りの回転が最初に行われ、次にyの周り、最後にxの周りが行われます'''。


よくある事象として、4つの数字を結合することで成り立つ'''rotation'''は分かりやすいけど、初心者が理解するには難しいというものです。幸いにも実際に内部で''rotaton''にて表現することが必要になるのは早々無く、簡単に変換をやり取りする関数があります。
 
 
回転を表す他の手段は、<X,Y,Z>の3つからなる数値を、オブジェクトの各軸回りの回転量({{LSLG/ja|radians|ラジアン}})として用いることです。これは例えばエディットウィンドウで用いられていて、人々が思い描くのがわりと容易です。この3つの数値は'''vector'''であって'''rotation'''型では無いことに注意してください。ですがそれらは同じ情報を表すことができます。これは回転のオイラー角表現と呼ばれます。
 
3番目の方法は、前方、上方、そして左側を指す3つのvectorを用いることです。実際には3つのうち2つのみが必要で、3つめの値は2つから求めます。
 
回転を合成できるなどのもっともな理由があるので、4つの数値からなる'''rotation'''は優れているのですが、初心者が理解するのはより難しいです。幸いにも、実際の''rotation''の内部表現で何かすることはめったに必要ありませんし、また簡単にこれらの間を変換する関数があります。
 
===軸に角度を加算===
この方法では、地球が回転する軸を定義し、その軸と回転軸周りの回転量を定義して、'''rotation''' を与えます。
 
例えば、x-y平面(リージョン座標では北東)で45度の'''rotation'''を定義したい場合、軸をxとyの同じ量で指す必要がありますが、zは使用しません。軸は<1.0, 1.0, 0.0>になります。軸を定義する数値の絶対サイズはこの表現では重要ではありません。例えば、<2.0, 2.0, 0.0>でも同様に動作します。'''rotation'''の角度は別のラジアンで与えられ、例えばPI/3(60度)です。これらの数値は、北東軸周りの60度のグローバルな'''rotation'''を定義します。
 
軸に角度を加算も四つの数値を使用しますが、"正規化"される必要はありません。
 
===FWD, LEFT, UP===
同じ3Dの角度を表現する別の方法は、前方が何を指しているか(fwd)、上部が何を指しているか(up)、そして左側が何を指しているか(left)を示す3つのベクトルを使用することです。 実際には、3つのうちの2つだけが必要です。 なぜなら、2つのベクトルを使用すると、残りの1つを決定できるからです。
 
良い理由があるため、例えば'''rotation'''を簡単に組み合わせることができるように、四つの数値バージョンであるクォータニオンの'''rotation'''がより良いですが、初心者にとって理解が難しいかもしれません。 幸いなことに、'''rotation'''の実際の内部表現で何かを行う必要があることはほとんどなく、3つのLSLタイプと度とラジアンの間を簡単に変換するための関数が存在します。


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


http://en.wikipedia.org/wiki/Right_hand_rule
http://ja.wikipedia.org/wiki/右手の法則


また、右手を動かさないまま、有効な回転方向の決定にも使います。右手を握り、親指を立てて、好きな軸の方向をさします。人差し指と中指を有効なrotationの方向に向けて曲げます。Rotationは、X、Y、Z軸と回転、傾斜角度、揺れを参照する、よくある特殊な伝達手段です。
さて、右手はまだ戻さないでください。正方向の回転の向きを求めるという別の使い道があります。右手を握り、親指を立てて好きな軸の正方向を指します。あなたの他の指は正方向の回転の向きに曲がります。x,y,z軸周りの回転は特に乗り物において、しばしばロール、ピッチ、ヨーとして示されます。


[http://en.wikipedia.org/wiki/Tait-Bryan_angles Roll Pitch Yaw]
http://ja.wikipedia.org/wiki/ローリング ・ http://ja.wikipedia.org/wiki/ピッチング ・ http://ja.wikipedia.org/wiki/ヨーイング


==Rotationの結合==
==Rotationの合成==
'''Rotation'''を結合するには、'''掛け算'''と'''割り算'''の演算子を用います。'''rotation'''への足し算もしくは引き算の演算子は予期する動作にはならないので、使おうとはしないでください。'''掛け算'''の演算子は
考えてみましょう。2つの回転があると仮定しましょう。''r1'' は左に90度回転し、''r2'' は右に30度回転します。(どの回転でも構いません;これは単なる例です。)
方向の加算に、'''割り算'''の演算子は方向の引き算に応用されます。つまり、X.s = -X.sのような構成ではないということです。
* 演算子を使用して ''r1'' と r2 を結合して、''r3'' を作成できます。実際にはそれらを「掛け算」するのではなく、それらを「合成」します。
{{LSLG|float/ja|float}}以外の型は、floatに変換されます。
<source lang="lsl2">
[http://en.wikipedia.org/wiki/Commutative non-commutative]が重要です。
rotation r3 = r1 * r2;
rotatonへの変換はRLで重要で、理由は単純です。例えば、4つの羽のあるダーツを持っていたとして、rotation<0,0,0>の尾尻から始めて、有効なX軸方面に照準をつけ、羽をZとY軸のみにし、そしてダーツの軸とダーツ盤の軸を一直線上にします。私達はXを45度前後で、Yを30度前後回転させてやっていますが、それは間違いです。
</source>


始めに、X軸を45度回転の後にダーツはX軸上にまだあり、ぶれないまま、長時間軸にそって回転したあと、ダーツは軸を45度にするでしょう。Y軸を30度前後回転しているダーツは、X軸から30度XZ面へ降下するでしょう(rotationでのフレミングの法則は、降下移動したY軸の周囲で小さく有効に回転する、という意味だと思い出しましょう)。ダーツ風の上昇先を30度下げ、飛び始めと同じ高さを飛びますが、ダーツはそう長くは昇降せずに長時間軸に沿って回転されます。
'''Rotation'''を合成するには、'''掛け算'''と'''割り算'''の演算子を用います。'''rotation'''への足し算もしくは引き算の演算子は予期する動作にはならないので、使おうとはしないでください。'''掛け算'''の演算子は
正方向の回転に、'''割り算'''の演算子は負方向の回転に用いられます。X.s = -X.sのようにして成分sを直接反転させて回転を反転させることもできます。


ほかの方法を取るとするならば、最初にY軸を30度回転させて、ダーツがXZ面に回転降下するのでしょうが、X軸上にはそう長くはいないことに注目します。ダーツのX軸とダーツ板が一直線上にはならないからです。今X軸周りを45度回転するダーツは、ダーツの尾尻を中心にし、40度右上がり向きに、長時間有効なダーツ板のX軸が30度の円錐上にあるポイントへ従います。X軸へと降下しているように見えたなら、ダーツはX軸の30度以下のポイントから旋回し、右上がりにXZ面上から出て、XY面上の最初の四分儀以下のポイントへ、ダーツは回転して進みます。
他のデータ型(例:{{LSLG/ja|float|float}})とは異なり、操作の順序、[http://ja.wikipedia.org/wiki/%E4%BA%A4%E6%8F%9B%E6%B3%95%E5%89%87 非可換]、が重要です。その理由は単純です。回転を行う順序はRLで重要です。たとえば、4本の羽を持つダーツを、回転 <0, 0, 0> から始め、その尾が原点にある状態から考えてみましょう。これはX軸に沿っており、先が正のX方向を指しており、羽はZ軸とY軸に沿っています。ダーツの軸と世界の軸が揃っています。これをX軸を中心に45度回転させ、Y軸を中心に30度回転させることになりますが、異なる順序で行います。


明らかにこれは最初のrotationとは異なる結果ですが、rotationの結果が変えられるだけのことです。
最初に、X軸を中心に45度回転すると、ダーツはX軸上にあり、移動せず、ただ長い軸に沿って回転します。したがって、羽は軸に対して45度の角度を持つことになります。次に、Y軸を中心に30度回転すると、ダーツはXZ平面内でX軸から30度下を指すようになります(回転の右手ルールによれば、Y軸を中心に小さな正の回転は点を下に移動させます)。ダーツは下を向いており、始めにいたのと同じ垂直平面にありますが、自分自身の長い軸を中心に回転しているため、羽が上下ではなくなっています。


ラジアンの構成(オイラーアングルと呼ばれる)で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}}にしましょう。
逆の順序で行った場合、まずY軸を中心に30度回転すると、ダーツはXZ平面内で下に回転しますが、注意してください、もはやX軸上にはありません。ダーツのX軸と世界のX軸はもはや揃っていません。今度はX軸を中心に45度回転させると、ダーツは尾を中心に回転し、点はX軸が正の方向にある世界のXY平面の第1象限の下にある点へと移動します。羽も回転しながら移動します。


'''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">
一定の回転を行うには、X、Y、Zの角度を成分として持つ{{LSLG/ja|vector}}を作成し(これはオイラー角と呼ばれます)、それを{{LSLG/ja|llEuler2Rot}}関数を使用して{{LSLG/ja|rotation}}に変換する必要があります。回転からオイラー角に変換するには、{{LSLG/ja|llRot2Euler}}を使用します。
{| cellpadding=0 cellspacing=0
 
|-
軸回転を行いたい場合は、回転の軸と回転角度を{{LSLG/ja|llAxisAngle2Rot}}関数に挿入し、これにより{{LSLG/ja|rotation}}が返されます。回転から軸と角度に戻すには、{{LSLG/ja|llRot2Axis}}と{{LSLG/ja|llRot2Angle}}を使用します。
|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}}へ逆変換します。(値はラジアンとなるでしょう。)
 
|}
'''NOTE:'''LSLでの角度はラジアンであって度ではありませんが、組み込み定数[[#RAD_TO_DEG|RAD_TO_DEG]] と [[#DEG_TO_RAD|DEG_TO_RAD]]を使うことで簡単に変換できます。X軸周りの30度の'''rotation'''に対して以下のように使うこともできます:
</div></div>
<source lang="lsl2">
rotation rot30X = llEuler2Rot(<30, 0, 0>*DEG_TO_RAD);           // 度をラジアンに変換してから、{{LSLG/ja|vector|vector}}をrotationのrot30xに代入します。
vector   vec30X = llRot2Euler(rot30X);                         // rotationから{{LSLG/ja|vector|vector}}へ逆変換します。(値はラジアンとなるでしょう。)
rotation rot30X = llAxisAngle2Rot(<1, 0, 0>, 30.0*DEG_TO_RAD);  // 度をラジアンに変換してから、ラジアンの値をrot30xに変換します
</source>
 
== Differences between math's quaternions and LSL rotations ==
 
数学のクォータニオンとLSLの回転にはいくつかの違いがあり、スクリプトを作成する際にはあまり影響がないかもしれませんが、数学の知識を持つ人々を困惑させる可能性があるため、それらをここにリストアップすることが良いと考えました。:
 
*LSLでは、すべてのクォータニオンは正規化されています('''R'''による'''R'''の内積は常に'''1'''です)。したがって、オブジェクトのサイズを変更せずに回転させる方法を表します。数学では、一般的なクォータニオンは正規化されていない場合があり、オブジェクトのサイズを変更する方法を表します。
* LSLでは、'''s'''の項目は回転の4番目のメンバーです:'''<x, y, z, s>'''。数学では、'''s'''の項目、または「実部」とも呼ばれるものは、クォータニオンの最初の座標として書かれます:'''(s, x, y, z)'''。
* 乗算はLSLと数学では逆の順序で書かれています。LSLでは、'''R * S'''と書きますが、数学では'''S . R'''と書きます。
 
==オイラーベクトルでの回転の順番==


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


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


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


インワールドに相対な'''rotation'''とローカルオブジェクト自身に相対な'''rotation'''とを区別することは重要です。エディタにて、お互いをいったりきたりさせることができます。スクリプトにて、望ましい振る舞いを得るために互いに変換させるべきです。
'''ローカル'''の回転は、オブジェクトがワールド内でどんな回転をしているかに関わらないオブジェクト自身の前後、左右、上下に当てはめられた軸周りでの回転です。'''グローバル'''の回転は南北、東西、上下のワールドの軸周りでの回転です。あなたはプリムの回転の違いを見ることができ、編集やローカルとグローバルの軸の設定を色のついた矢印が変わるの注意しながら変更することができます。


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


LSLでは、rotationを''ローカル''''''グローバル'''にするかの違いは、ステートメントでrotationの評価される方法によります。
これは、30度の一定の'''rotation'''をオブジェクトの最初の'''rotation'''(myRot)の左側につけることで'''ローカル'''での30度の回転を行います。それは上述のダーツをその長軸の周りに30度にねじる最初の例の最初の操作に似ています。


このrotationは、一定の30度の'''rotation'''へオブジェクトが左向きに''rotation'''(myRot)を開始している状態によるものが''ローカル'''の30度のrotationです。最初の例であげた最初の演算の、ダーツ自身の長軸周りをダーツが30度ひねっているものようなものです。
<source lang="lsl2">
rotation localRot = rot30X * myRot;// ワールドの回転に一定の回転をかけることでローカルの回転を行う。
</source>


<div id="box"><div style="padding: 0.5em">
'''グローバル'''の回転をするためには同じ'''rotation'''を使いますが、順番は逆にしてください。これはダーツが上昇回転してワールドのX軸周りに右に回る2番目の例の2番目の操作に似ています。この場合、既存のrotation(myRot)はグローバルのX軸の周りで30度回転します。
{| cellpadding=0 cellspacing=0
|-
|rotation localRot = ||rot30X * myRot;||// 空間のrotationによる、一定のrotationtで掛け算されたローカルのrotationを行ないます。
|}
</div></div>


同じ'''rotation'''の値を用いて'''グローバル'''rotationをすることは、その逆の命令ということではありません。これは2つめの例の2つめの演算で、ダーツが上昇回転して、空間のX軸にそって右に回るようなものです。このケースでは、存在しているrotation(myrot)はグローバルのX軸周りを30度回転しています。
<source lang="lsl2">
rotation globalRot = myRot * rot30X;// 一定の回転をワールドの回転にかけることでグローバルの回転を行う。
</source>


<div id="box"><div style="padding: 0.5em">
==rotationの結合について考える他の方法==
{| cellpadding=0 cellspacing=0
|-
|rotation globalRot || = myRot * rot30X;||// 一定のrotationにより、空間のrotationで掛け算されたグローバルのrotationを行ないます。
|}
</div></div>


==rotationの結合について他の方法を考える==
あなたは'''ローカル'''と'''グローバル'''の違いについて、括弧以外は左から右へと評価されるという'''rotation'''の評価順序から考えてみたいかもしれません。


左右を括弧で覆われたものを除いて、評価する命令の中で行なわれる'''rotation'''を考えることにより、この'''ローカル'''対'''グローバル'''の違いについて考えたくなるでしょう。
localRotの場合は、<0, 0, 0>から始まって、rot30Xが最初に行われ、ワールドのX軸回りにプリムが回転し、回転の始まる時点からローカルとグローバルの軸はオブジェクトのローカルのX軸に沿った同一の回転をします。
そして、2つめの'''rotation'''であるmyRotは、プリムをオリジナルのrotationで回転させましたが、さらにX軸の回転が焼きつきます。
これは、プリムの回転がそのX軸に沿ってYとZの'''rotation'''が変わらないローカル回転のようになります。


<0,0,0>から始まって発生するlocalRotのケースではrot30Xが最初に行なわれ、空間のX軸にそってプリムが回転し、回転している間は、ローカルとグローバルの角度はオブジェクトのローカルX軸に沿っての回転を行なう効果を識別します。2つめの'''rotation'''であるmyRotはプリムをオリジナルのrotationに回転させましたが、それではさらにX軸のrotationが焼きつきます。何と、これはプリムがX軸にそって回転して、YとZのrotationが変わらなかった'''ローカル'''rotationのようなものです。
globalRotの場合は、再び<0, 0, 0>から始まって、まずオブジェクトがオリジナルのrotation(myRot)で回転しますが、オブジェクトの軸とワールドの軸はもはや一致しません!そして、2つめの'''rotation'''であるrot30xは、まさにローカルの場合と同様に、オブジェクトをワールドのX軸回りに30度回転しますが、その効果はオブジェクトをワールドのX軸に沿って円錐を回転させます。オブジェクトのX軸とワールドのX軸はこの時点では一致しません。プリムはワールドのX軸の沿って30度回転するように見えます。そのため'''global''' 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'''の割り算は、反対の方向のrotationにする効果があり、330度のrotationによる掛け算は、30度の'''rotation'''による割り算と同じです。
==rotationを使う==
==rotationを使う==


'''R.x、R.y、R.z、 そしてR.s'''(R.w'''ではありません''')による'''rotation'''Rの特定の構成でアクセスが可能です。スカラー部R.sはrotationのアングルの半分のコサインです。vector部(R.x、R.y、R.z)はrotationの一般的な角度とrotationのアングルの半分のサインの積です。x、y、zが無効になることによる(あるいは無効な値をつくることにより)、逆の'''rotation'''を生成可能です。余談ですが、{{LSLG|float/ja|float}} 値のリポジトリとして'''rotation'''を使うことも可能で、各'''rotation'''は4つの{{LSLG|float/ja|float}} 値を貯蓄し、'''rotation'''から成り立つ{{LSLG|list/ja|list}}は{{LSLG|float/ja|float}}の集まりから成り立つ{{LSLG|list/ja|list}}よりもさらに効率的ですが、それの中身を覗くのはコストが高いでしょう。
'''rotation R'''のそれぞれの要素には'''R.x, R.y, R.zとR.s''' (R.w'''ではありません''')からアクセスできます。スカラ部分のR.sは回転角の2分の1のコサインです。ベクタ部分(R.x,R.y,R.z)は正規化した回転軸と回転角の2分の1のサインの積です。x,y,z要素の符号を反転することにより(または、sの符号を反転させることにより)逆の'''rotation'''を作ることができます。余談ですが、{{LSLG/ja|float|float}}値の格納場所として'''rotation'''を使うことも可能です。各'''rotation'''は4つの{{LSLG/ja|float|float}} 値を格納し、'''rotation'''から成る{{LSLG/ja|list|list}}は{{LSLG/ja|float|float}}の集まりの{{LSLG/ja|list|list}}よりもさらに効率的ですが中身を覗くのはコストが高いでしょう。
 
<source lang="lsl2">
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を作ります
</source>
 
ゼロ回転の組み込み定数として[[#ZERO_ROTATION|ZERO_ROTATION]]があり、'''rotation R'''を反転させたい場合は[[#ZERO_ROTATION|ZERO_ROTATION]]を'''R'''で割ります。上記の注意として、これはまずゼロ位置への回転となり、そして除算なので元の'''rotation'''の反対向きへの回転となり、その結果逆回転します。
<source lang="lsl2">
rotation rot330X        = <-rot30X.x, -rot30X.y, -rot30X.z, rot30X.s>;//  回転の反転 - 注意 要素sの符号は反転していません
rotation another330X    = ZERO_ROTATION / rot30X;                    //  除算による回転の反転、rot330Xと同じ結果となります
rotation yetanother330X = <rot30X.x, rot30X.y, rot30X.z, -rot30X.s>;  //  まったく同じではありませんが同じ結果となります。
</source>
 
==単一またはルートプリム vs リンクプリム vs アタッチメント ==
 
単一またはリンクプリムの回転について語る理由として、どんなビークル全体の回転があっても対応してドアが動くという望ましい動きするビークルのドアなどのためです。グローバルな回転でこれを行える間はそれはとても退屈でしょう。通常、プリムが扱える座標系には単独、{{LSLG/ja|linkset}}の一部、{{LSLG/ja|attachment}}の一部の3つがあります。プリム単独のとき、すなわち{{LSLG/ja|linkset}}ではない場合は、ルートプリムのように振舞います; {{LSLG/ja|attachment}}の一部の場合は、それは異なった少し壊れている振る舞いをします。
 
{{LSLRotGetSet/ja}}
 
==Vectorの回転==
 
LSLでは{{LSLG/ja|vector|vector}}を回転させるのは回転の中心がオブジェクトの中心ではないオブジェクトを弧や円状に動かしたいときにとても役立ちます。
 
これはとても複雑に思えますが、これにはここで目にするより多くのことがあります。上述の[[#Combining Rotations|ダーツ]]に関する議論を思い出して、物理的なダーツを元点がダーツの尾部にありダーツの先端の位置をX,Y,Z要素とする{{LSLG/ja|vector|vector}}に置き換えてみてください。ダーツの尾部回りの回転はダーツの先端をダーツの尾部を中心とした弧に沿って動かします。まさに同様にプリムの中心からずれを表す{{LSLG/ja|vector|vector}}の回転は同じ弧を通りプリムを回転させます。これは{{LSLG/ja|vector|vector}}によりプリムの中心からずれた位置の周りでのオブジェクトの回転に見えます。


<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|DEG_TO_RAD]] );||// rotation定数を作成する
|rotation rot6X ||= {{LSLG/ja|llEuler2Rot}}(<30, 0, 0> * [[#DEG_TO_RAD|DEG_TO_RAD]] );||// [[Viewer_coordinate_frames/ja#Local|local]]のX軸回りに30度するrotationの定数を作成する
|-
|-
|rotation rotCopy ||= rot30X;||// rotCopyに全4つのfloatの構成をコピーします
|vector offset ||= <0, 1, 0>;||// [[Viewer_coordinate_frames/ja#Local|local]]のY方向へ正の向きで1mのオフセットを作成する
|-
|-
|float X ||= rotCopy.x;||// rotationの特定の構成を出力します
|vector rotatedOffset || = offset * rot6X;||// rotationによる動きを得るためにオフセットを回転する
|-
|-
|float Y ||= rotCopy.y;||
|vector newPos || = {{LSLG/ja|llGetPos}}() + (offset - rotatedOffset) * {{LSLG/ja|llGetRot}}();||// 回転したオフセット分だけプリムの位置を動かします
|-
|-
|float Z ||= rotCopy.z;||
|rotation newRot|| = rot6X * {{LSLG/ja|llGetRot}}();||// オフセット点を向くために回転を変更します
|-
|float S ||= rotCopy.s;||
|-
|rotation anotherCopy ||= <X, Y, Z, S>;||// 構成から他のrotationを作ります
|}
|}
</div></div>
</div></div>
<source lang="lsl2">
//-- same as:
llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (gPosOffset - gPosOffset * gRotArc) * llGetRot(),
                      PRIM_ROTATION, gRotArc * llGetRot()] );
</source>
'''注意:''' これによる移動はプリムを地下や10m以上移動させる結果にもなることを忘れないでください。


 
オブジェクトの現在の向きに対応した点を得る(rezzorsなどに使います)
直接、あるいは'''rotation R'''を反転する必要があるならば、'''R'''によって[[#ZERO_ROTATION|ZERO_ROTATION]]を分割して使うことが出来る、zero '''rotation'''のビルトイン定数があります。上記の注意として、最初のzero potitionの回転による作業は 次にそれを分割させるため、オリジナルの'''rotation'''の逆向きに回転させ、その結果反転の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 rot330X ||= <-rot30X.x, -rot30X.y, -rot30X.z, rot30X.s>;||// rotationの反転 - この構成は有効ではありません
|rotation rotFacing ||= {{LSLG/ja|llGetRot}}();||// オブジェクトの現在のrotationを得る
|-
|vector offset ||= <0, 0, 1>;||// [[Viewer_coordinate_frames/ja#Local|local]]のZ方向へ正の向きに1mのオフセットを作成する
|-
|-
|rotation another330X ||= [[#ZERO_ROTATION|ZERO_ROTATION]] / rot30X;||// 割り算によるrotationの反転で、rot330Xと結果は同じです
|vector rotatedOffset || = offset * rotFacing;||// 対応するオブジェクトの回転へオフセットを回転する
|-
|-
|rotation yetanother330X ||= <rot30X.x, rot30X.y, rot30X.z, -rot30X.s>;||// まったくの同じものではありませんが、同じ働きをします
|vector correctOffset || = {{LSLG/ja|llGetPos}}() + rotatedOffset;||// ローカルオフセットの[[Viewer_coordinate_frames/ja#Region|region]]上の位置を得る
|}
|}
</div></div>
</div></div>
<source lang="lsl2">
//-- same as:
vector correctOffset = llGetPos() + offset * llGetRot();
</source>
=== Position of Object Rotated Around A Relative Point ===
<source lang="lsl2">rotation vRotArc      = llEuler2Rot( <30.0, 0.0, 0.0> * DEG_TO_RAD );
//-- creates a rotation constant, 30 degrees around the X axis
vector  vPosOffset    = <0.0, 1.0, 0.0>;
//-- creates an offset one meter in the positive Y direction
vector  vPosRotOffset  = vPosOffset * vRotArc;
//-- rotates the offset to get the motion caused by the rotation


==単一もしくはルートプリム vs リンクプリム vs アタッチメント ==
vector  vPosOffsetDiff = vPosOffset - vPosRotOffset;
//-- gets the local difference between the current offset and the rotated one


単一かリンクプリムのrotationについて話す理由は乗り物のドラのようなもののためで、期待された動作は、たとえ乗り物全体のrotationに何があろうとも、乗り物と相対的にドアが動くことです。可能な限りこれをグローバルrotationにする間は、手をつけることすらないでしょう。
vector  vPosRotDiff    = vPosOffsetDiff * llGetRot();
プリムには独自で、{{LSLG|linkset}}の一部、{{LSLG|attachment}}の一部があり、一般的な3つの等位なシステムがあります。プリムが独立しているとき、たとえば{{LSLG|linkset}}の一部ではなく、ルーとプリムのように動いたり、{{LSLG|attachment}}の一部のときは、ちょっと壊れたような異なる動きをします。
//-- rotates the difference in the offsets to be relative to the global rotation.


{{LSLRotGetSet/ja}}
vector  vPosNew        = llGetPos() + vPosRotDiff;
//-- finds the prims new position by adding the rotated offset difference
 
rotation vRotNew        = vRotArc * llGetRot();
//-- finds rot to continue facing offset point</source>
:アプリケーションにおいて、以下の操作が行われています:
<source lang="lsl2">llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (vPosOffset - vPosOffset * vRotArc) * llGetRot(),
                      PRIM_ROTATION, vRotArc * llGetRot()] );</source>
* 上記の方法では、周回しているオブジェクトは常に中心に対して同じ側面を向いています。回転を保持する代替方法は次の通りです
<source lang="lsl2">llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (vPosOffset - vPosOffset * vRotArc) * llGetRot()];
vPosOffset = vPosOffset * vRotArc;</source>
'''注意''' これは移動操作ですので、オブジェクトをワールドの外に移動させたり、地下に埋めたり、10メートル以上移動させる場合の問題に注意してください。また、完全な軌道を得るためには、リストされたステップを繰り返す必要があります([[timer/ja|タイマー]]を使用することができます)。
 
'''注意''' これらはルートプリム(または好みに応じた子プリム)に適用されます。子プリムの場合、位置には[[PRIM_POS_LOCAL]]を、回転には[[PRIM_ROT_LOCAL]]または[[llGetLocalRot]]を使用し、回転の中心はルートに対して相対的である必要があります。
 
=== Position of Relative Point Around Rotated Object ===
オブジェクトの現在の向きに対して相対的なポイントを取得するには(rezzorsなどで使用されることがあります)、次のようにします。
<source lang="lsl2">vector  vPosOffset    = <0.0, 0.0, 1.0>;
//-- creates an offset one meter in the positive Z direction.
 
vector  vPosRotOffset  = vPosOffset * llGetRot();
//-- rotate the offset to be relative to objects rotation
 
vector  vPosOffsetIsAt = llGetPos() + vPosRotOffset;
//-- get the region position of the rotated offset</source>
:アプリケーションにおいて、以下の操作が行われています:
<source lang="lsl2">llRezAtRoot( "Object", llGetPos() + vPosOffset * llGetRot(), ZERO_VECTOR, ZERO_ROTATION, 0 );</source>
 
==Normalizing a Rotation ==
正確性が必要な場合、正規化された回転を使用することはしばしば重要であり、必要なことさえあります。これは、各四元数の 'x'、'y'、および 'z' の値が1に等しくなるようにスケーリングすることを意味します。LSLのいくつかの操作は、これを行わないと実行時エラーが発生する場合があります。別の視点で見ると、回転を、ベクトル<1.0、1.0、1.0>に回転角を適用する方法で表現する必要があります。数学的に、回転 'Q' を正規化することは次のように計算されます。


==Vectorの回転==
'''Normalized Q = Q / Sqrt( Q.x^2 + Q.y^2 + Q.z^2 + Q.s^2)'''


LSLで、rotationの中心がオブジェクトの中心はないときに輪や弧の中でオブジェクトを動かしたいのなら、{{LSLG|vector/ja|vector}}の回転はとても使い勝手がよいです。
Putting that in LSL terms:
<source lang="lsl2">rotation NormRot(rotation Q)
{
    float MagQ = llSqrt(Q.x*Q.x + Q.y*Q.y +Q.z*Q.z + Q.s*Q.s);
    return <Q.x/MagQ, Q.y/MagQ, Q.z/MagQ, Q.s/MagQ>;
}</source>
: '''Note''': 正規化されていない回転を取得するLSLの唯一の方法は、[[llAxes2Rot/ja]]('相互に直交していない入力'または '異なる大きさの入力'を介して)または回転の要素を直接操作することです。他のすべてのll*関数は正規化された回転を返します。前述の例の使用により、有限の精度の制約により、正規化された回転に小さな浮動小数点エラーが導入される可能性があります。


とても整っていますが、目で見るものは殆どありません。上記の[[#Combining Rotations|ダーツ]]の回転の議論を思い出しして、物理のダーツと{{LSLG|vector/ja|vector}}を、基点をダーツの尾尻、そしてX、Y、Zの構成ダーツの頂点のポジションと記述して、置き換えてみましょう。ダーツの尾尻にそって回転しているダーツは全体の頂点が移動し、rotationの中心はダーツの尾尻の弧です。まったく同じものは プリムの中心から同じ弧を通してプリムが回転する補正値を描写する、回転している{{LSLG|vector/ja|vector}}です。なんと、これはオブジェクトがプリムの中心からの{{LSLG|vector/ja|vector}}位置補正値周辺を回転するかのようにみえます。
==便利なスニペット==
文字列がRotationか判定
<div id="box"><div style="padding: 0.5em">
<source lang="lsl2">integer IsRotation(string s)
{| cellpadding=0 cellspacing=0
{
|-
    list split = llParseString2List(s, [" "], ["<", ">", ","]);
|rotation rot30X ||= {{LSLG|llEuler2Rot}}(<30, 0,0> * [[#DEG_TO_RAD|DEG_TO_RAD]] );||// X軸周りの30度のrotationの定数を作成します
    if(llGetListLength(split) != 9)//リスト長のチェックをしないと次のテストが正しく動きません
|-
        return 0;
|vector offset ||= <0, 1, 0>;||// グローバルの有効なY方向に補正値1メートルを作成します
    return !((string)((rotation)s) == (string)((rotation)((string)llListInsertList(split, ["-"], 7))));
|-
    //it works by trying to flip the sign on the S element of the rotation,
|vector rotatedOffset || = offset * rot30X;||// rotationによって発生した動きを取得する補正値で回転します
    //if it works or breaks the rotation then the values won't match.
|-
    //if the rotation was already broken then the sign flip will have no affect and the values will match
|vector newPos || = {{LSLG|llGetPos}}() + rotatedOffset;||// 補正値総数で回転したプリムのポジションを移動します
    //we cast back to string so we can catch negative zero which allows for support of <0,0,0,0>
|}
}//Strife Onizuka</source>
</div></div>


'''Nota Bene:''' これによっておこなう移動は、10mもしくはそれ以下の地下に埋まっているオフワールドのプリムが移動する問題について忘れてはいけません。
rotation をRoll Pitch Yawに分割
<source lang="lsl2"> // LindaB Helendale
// https://wiki.secondlife.com/wiki/User:LindaB_Helendale/rot2roll_pitch_yaw
vector rot2roll_pitch_yaw(rotation R)
{
    /*
    Convert rotation to roll, pitch and yaw angles
    (c) LindaB Helendale
    Permission to use this code in any way granted
   
    Input: rotation (quaternion) R
    Output: vector <roll,pitch,yaw>
   
    Roll, pitch and yaw are body-related rotations (intrinsic Tait-Bryan angles):
    first yaw to the heading, then pitch around the local Y-axis and then roll
    around the local X-axis (nose direction). This is equivalent to world coordinate
    rotations (extrinsic Tait-Bryan angles, or LSL Euler angles) in order roll, pitch and yaw.
    Thus the rotation R is recovered from the roll, pitch and yaw angles by inverting
    the order of the rotations (since in LSL they are in Z Y X or yaw, pitch, roll order):
        rotation R = llEuler2Rot(<roll,0,0>) * llEuler2Rot(<0,pitch,0>) * llEuler2Rot(<0,0,yaw>);
       
    Reference: http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
    */
    vector eulerXYZ = < llAtan2(2*(R.s*R.x+R.y*R.z),1-2*(R.x*R.x+R.y*R.y)),
                        llAsin(2*(R.s*R.y-R.z*R.x)),
                        llAtan2(2*(R.s*R.z+R.x*R.y), 1-2*(R.y*R.y+R.z*R.z)) >;
    return(eulerXYZ);
}
</source>
Roll Pitch Yawをrotationに変換
<source lang="lsl2"> // LindaB Helendale
// https://wiki.secondlife.com/wiki/User:LindaB_Helendale/rot2roll_pitch_yaw
rotation roll_pitch_yaw2rot(vector R)
{
    // convert vector <roll,pitch,yaw> to LSL rotation
    return llEuler2Rot(<R.x,0,0>) * llEuler2Rot(<0,R.y,0>) * llEuler2Rot(<0,0,R.z>);
}
</source>


==定数==
==定数==
=== [[ZERO_ROTATION]] ===
=== [[ZERO_ROTATION/ja|ZERO_ROTATION]] ===
ZERO_ROTATION = <0.0, 0.0, 0.0, 1.0>;<br/>
ZERO_ROTATION = <0.0, 0.0, 0.0, 1.0>;<br/>
このrotation定数は<0.0, 0.0, 0.0>のオイラーアングルの代数です。
オイラー角の<0.0, 0.0, 0.0>に相当するrotation定数
=== [[DEG_TO_RAD]] ===
=== [[DEG_TO_RAD/ja|DEG_TO_RAD]] ===
DEG_TO_RAD = 0.01745329238f;<br/>
DEG_TO_RAD = 0.01745329238f;<br/>
DEGREES(角度)のアングルをラジアンのアングルに渡して乗算するときのfloat定数です。
角度(°)から乗算でラジアン角を得るときのfloat定数


=== [[RAD_TO_DEG]] ===
=== [[RAD_TO_DEG/ja|RAD_TO_DEG]] ===
RAD_TO_DEG = 57.29578f;<br/>
RAD_TO_DEG = 57.29578f;<br/>
ラジアンのアングルをDEGREES(角度)のアングルに渡して乗算するときのfloat定数です。
ラジアン角から乗算で角度(°)を得るときのfloat定数
 


[[Category:LSL_Types|Rotation]][[Category:LSL_Math]][[Category:LSL_Math/3D]][[Category:LSL_Constants/ja]]
{{LSLC/ja|Types}}
{{LSLC/ja|Math}}
{{LSLC/ja|Math/3D}}

Latest revision as of 17:41, 3 October 2023

Rotation

回転 は 4つの浮動小数点値 を含むデータ型です。

各要素は、変数名に .x.y.z、または .s を追加することで個別にアクセスできます。

rotation rot;
float x = rot.x;
float y = rot.y;
float z = rot.z;
float s = rot.s;

LSL のrotation型は3Dでの方位を表すのに用いられます。(型名を太字で書くように心がけています。)方位あるいは3Dアングルはクォータニオンと呼ばれる数学的オブジェクトによって表されます。クォータニオンは4つの数値から成ると考えることができ、3つがオブジェクトの向いている方向を表し、4つめがその方向の周りでのオブジェクトの右か左への傾きを表します。クォータニオンを用いる主な利点は、ジンバルロックの影響を受けないことです。 クォータニオン数学の込み入った内部処理はクォータニオンを参照してください。 rotationに関連する関数とイベントの一覧はRotation Synopsisを参照してください。 テクスチャの項にテクスチャの回転に関しての情報があります。

回転はしばしば非常に混乱するトピックと見なされ、スクリプターは試行錯誤して正確な結果を得ることがあります。この混乱の理由は次のとおりです:

  • 誰もが本当の意味でクォータニオン が何であり、それをどのように考えるべきかを正確に知らない(完全には真実ではありませんが、脳は4つの幾何学的次元で考えることが得意ではありません)。
  • 実際には異なるタイプのベクトル('dir'、'vec'、'pos')がいくつかあり、それぞれ異なる方法で操作する必要があります。
  • 移動と回転を適用する順序はケースによって異なる場合があります。
  • 適用された回転と座標系間の回転 'オフセット' の違いについて混乱があります。

したがって、回転をマスターするには、変数のための良い命名システムを使用することが不可欠です。このようなシステムは、About Coordinate Systems and RotationsTimmy Foxclawによって詳しく説明されています。

その他の表現

Euler vector

3D角度を表す別の方法は、<X、Y、Z> という3つの数値を使用することです。これらの数値は、オブジェクトが各軸を中心に回転する量を表します。たとえば、これは編集ウィンドウで使用され、一般的には人々が視覚化しやすいです。編集ウィンドウでの回転 <x、y、z> 数値を調整し、オブジェクトの挙動を確認するのは簡単です。編集ウィンドウでは、数値は度数で表されます。つまり、直角は90度です。

LSLでは、これらの3つの角度は度数ではなくラジアンで表されます。つまり、直角はPI/2です。ラジアンは非常に幅広い度数のようなものです。 これらの3つの数値は、回転型ではなくベクトル型であり、同じ情報を表すことができます。これは3D角度の オイラー 表現と呼ばれます。LSLでは、zの周りの回転が最初に行われ、次にyの周り、最後にxの周りが行われます


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

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

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

軸に角度を加算

この方法では、地球が回転する軸を定義し、その軸と回転軸周りの回転量を定義して、rotation を与えます。

例えば、x-y平面(リージョン座標では北東)で45度のrotationを定義したい場合、軸をxとyの同じ量で指す必要がありますが、zは使用しません。軸は<1.0, 1.0, 0.0>になります。軸を定義する数値の絶対サイズはこの表現では重要ではありません。例えば、<2.0, 2.0, 0.0>でも同様に動作します。rotationの角度は別のラジアンで与えられ、例えばPI/3(60度)です。これらの数値は、北東軸周りの60度のグローバルなrotationを定義します。

軸に角度を加算も四つの数値を使用しますが、"正規化"される必要はありません。

FWD, LEFT, UP

同じ3Dの角度を表現する別の方法は、前方が何を指しているか(fwd)、上部が何を指しているか(up)、そして左側が何を指しているか(left)を示す3つのベクトルを使用することです。 実際には、3つのうちの2つだけが必要です。 なぜなら、2つのベクトルを使用すると、残りの1つを決定できるからです。

良い理由があるため、例えばrotationを簡単に組み合わせることができるように、四つの数値バージョンであるクォータニオンのrotationがより良いですが、初心者にとって理解が難しいかもしれません。 幸いなことに、rotationの実際の内部表現で何かを行う必要があることはほとんどなく、3つのLSLタイプと度とラジアンの間を簡単に変換するための関数が存在します。

右手ルール

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

http://ja.wikipedia.org/wiki/右手の法則

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

http://ja.wikipedia.org/wiki/ローリングhttp://ja.wikipedia.org/wiki/ピッチングhttp://ja.wikipedia.org/wiki/ヨーイング

Rotationの合成

考えてみましょう。2つの回転があると仮定しましょう。r1 は左に90度回転し、r2 は右に30度回転します。(どの回転でも構いません;これは単なる例です。)

  • 演算子を使用して r1 と r2 を結合して、r3 を作成できます。実際にはそれらを「掛け算」するのではなく、それらを「合成」します。
rotation r3 = r1 * r2;

Rotationを合成するには、掛け算割り算の演算子を用います。rotationへの足し算もしくは引き算の演算子は予期する動作にはならないので、使おうとはしないでください。掛け算の演算子は 正方向の回転に、割り算の演算子は負方向の回転に用いられます。X.s = -X.sのようにして成分sを直接反転させて回転を反転させることもできます。

他のデータ型(例:float)とは異なり、操作の順序、非可換、が重要です。その理由は単純です。回転を行う順序はRLで重要です。たとえば、4本の羽を持つダーツを、回転 <0, 0, 0> から始め、その尾が原点にある状態から考えてみましょう。これはX軸に沿っており、先が正のX方向を指しており、羽はZ軸とY軸に沿っています。ダーツの軸と世界の軸が揃っています。これをX軸を中心に45度回転させ、Y軸を中心に30度回転させることになりますが、異なる順序で行います。

最初に、X軸を中心に45度回転すると、ダーツはX軸上にあり、移動せず、ただ長い軸に沿って回転します。したがって、羽は軸に対して45度の角度を持つことになります。次に、Y軸を中心に30度回転すると、ダーツはXZ平面内でX軸から30度下を指すようになります(回転の右手ルールによれば、Y軸を中心に小さな正の回転は点を下に移動させます)。ダーツは下を向いており、始めにいたのと同じ垂直平面にありますが、自分自身の長い軸を中心に回転しているため、羽が上下ではなくなっています。

逆の順序で行った場合、まずY軸を中心に30度回転すると、ダーツはXZ平面内で下に回転しますが、注意してください、もはやX軸上にはありません。ダーツのX軸と世界のX軸はもはや揃っていません。今度はX軸を中心に45度回転させると、ダーツは尾を中心に回転し、点はX軸が正の方向にある世界のXY平面の第1象限の下にある点へと移動します。羽も回転しながら移動します。

明らかに、これは最初の回転とは異なる結果ですが、回転の順序が変更されただけです。

一定の回転を行うには、X、Y、Zの角度を成分として持つvectorを作成し(これはオイラー角と呼ばれます)、それをllEuler2Rot関数を使用してrotationに変換する必要があります。回転からオイラー角に変換するには、llRot2Eulerを使用します。

軸回転を行いたい場合は、回転の軸と回転角度をllAxisAngle2Rot関数に挿入し、これによりrotationが返されます。回転から軸と角度に戻すには、llRot2AxisllRot2Angleを使用します。

代替方法として、ネイティブな回転を直接作成することもできます。実数部分は回転角の半分の余弦であり、ベクトル部分は回転の軸を正規化し、角度の半分の正弦で乗算したものです。

NOTE:LSLでの角度はラジアンであって度ではありませんが、組み込み定数RAD_TO_DEGDEG_TO_RADを使うことで簡単に変換できます。X軸周りの30度のrotationに対して以下のように使うこともできます:

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

Differences between math's quaternions and LSL rotations

数学のクォータニオンとLSLの回転にはいくつかの違いがあり、スクリプトを作成する際にはあまり影響がないかもしれませんが、数学の知識を持つ人々を困惑させる可能性があるため、それらをここにリストアップすることが良いと考えました。:

  • LSLでは、すべてのクォータニオンは正規化されています(RによるRの内積は常に1です)。したがって、オブジェクトのサイズを変更せずに回転させる方法を表します。数学では、一般的なクォータニオンは正規化されていない場合があり、オブジェクトのサイズを変更する方法を表します。
  • LSLでは、sの項目は回転の4番目のメンバーです:<x, y, z, s>。数学では、sの項目、または「実部」とも呼ばれるものは、クォータニオンの最初の座標として書かれます:(s, x, y, z)
  • 乗算はLSLと数学では逆の順序で書かれています。LSLでは、R * Sと書きますが、数学ではS . Rと書きます。

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

上述の議論より1つ以上の軸で回転する場合、それらの回転する順番が重要となるのは明らかです。オイラーの議論ではこれはちょっと少しごまかしました。3つの軸周りの個々の回転は総合的な回転を定義します。しかし、それでは疑問が浮かびます: どんな軸の順番で回転しているのか? その答えはグローバル座標系ではZ,Y,Xです。オブジェクトをオイラー表現を用いて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の評価順序から考えてみたいかもしれません。

localRotの場合は、<0, 0, 0>から始まって、rot30Xが最初に行われ、ワールドのX軸回りにプリムが回転し、回転の始まる時点からローカルとグローバルの軸はオブジェクトのローカルのX軸に沿った同一の回転をします。 そして、2つめのrotationであるmyRotは、プリムをオリジナルのrotationで回転させましたが、さらにX軸の回転が焼きつきます。 これは、プリムの回転がそのX軸に沿ってYとZのrotationが変わらないローカル回転のようになります。

globalRotの場合は、再び<0, 0, 0>から始まって、まずオブジェクトがオリジナルのrotation(myRot)で回転しますが、オブジェクトの軸とワールドの軸はもはや一致しません!そして、2つめのrotationであるrot30xは、まさにローカルの場合と同様に、オブジェクトをワールドのX軸回りに30度回転しますが、その効果はオブジェクトをワールドのX軸に沿って円錐を回転させます。オブジェクトのX軸とワールドのX軸はこの時点では一致しません。プリムはワールドのX軸の沿って30度回転するように見えます。そのためglobal rotationのようになります。

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

rotationを使う

rotation Rのそれぞれの要素にはR.x, R.y, R.zとR.s (R.wではありません)からアクセスできます。スカラ部分のR.sは回転角の2分の1のコサインです。ベクタ部分(R.x,R.y,R.z)は正規化した回転軸と回転角の2分の1のサインの積です。x,y,z要素の符号を反転することにより(または、sの符号を反転させることにより)逆の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を作ります

ゼロ回転の組み込み定数としてZERO_ROTATIONがあり、rotation Rを反転させたい場合はZERO_ROTATIONRで割ります。上記の注意として、これはまずゼロ位置への回転となり、そして除算なので元のrotationの反対向きへの回転となり、その結果逆回転します。

rotation rot330X        = <-rot30X.x, -rot30X.y, -rot30X.z, rot30X.s>;//  回転の反転 - 注意 要素sの符号は反転していません
rotation another330X    = ZERO_ROTATION / rot30X;                     //  除算による回転の反転、rot330Xと同じ結果となります
rotation yetanother330X = <rot30X.x, rot30X.y, rot30X.z, -rot30X.s>;  //  まったく同じではありませんが同じ結果となります。

単一またはルートプリム vs リンクプリム vs アタッチメント

単一またはリンクプリムの回転について語る理由として、どんなビークル全体の回転があっても対応してドアが動くという望ましい動きするビークルのドアなどのためです。グローバルな回転でこれを行える間はそれはとても退屈でしょう。通常、プリムが扱える座標系には単独、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ではvectorを回転させるのは回転の中心がオブジェクトの中心ではないオブジェクトを弧や円状に動かしたいときにとても役立ちます。

これはとても複雑に思えますが、これにはここで目にするより多くのことがあります。上述のダーツに関する議論を思い出して、物理的なダーツを元点がダーツの尾部にありダーツの先端の位置をX,Y,Z要素とするvectorに置き換えてみてください。ダーツの尾部回りの回転はダーツの先端をダーツの尾部を中心とした弧に沿って動かします。まさに同様にプリムの中心からずれを表すvectorの回転は同じ弧を通りプリムを回転させます。これはvectorによりプリムの中心からずれた位置の周りでのオブジェクトの回転に見えます。

rotation rot6X = llEuler2Rot(<30, 0, 0> * DEG_TO_RAD ); // localのX軸回りに30度するrotationの定数を作成する
vector offset = <0, 1, 0>; // localのY方向へ正の向きで1mのオフセットを作成する
vector rotatedOffset = offset * rot6X; // rotationによる動きを得るためにオフセットを回転する
vector newPos = llGetPos() + (offset - rotatedOffset) * llGetRot(); // 回転したオフセット分だけプリムの位置を動かします
rotation newRot = rot6X * llGetRot(); // オフセット点を向くために回転を変更します
//-- same as:
llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (gPosOffset - gPosOffset * gRotArc) * llGetRot(),
                       PRIM_ROTATION, gRotArc * llGetRot()] );

注意: これによる移動はプリムを地下や10m以上移動させる結果にもなることを忘れないでください。

オブジェクトの現在の向きに対応した点を得る(rezzorsなどに使います)

rotation rotFacing = llGetRot(); // オブジェクトの現在のrotationを得る
vector offset = <0, 0, 1>; // localのZ方向へ正の向きに1mのオフセットを作成する
vector rotatedOffset = offset * rotFacing; // 対応するオブジェクトの回転へオフセットを回転する
vector correctOffset = llGetPos() + rotatedOffset; // ローカルオフセットのregion上の位置を得る
//-- same as:
vector correctOffset = llGetPos() + offset * llGetRot();

Position of Object Rotated Around A Relative Point

rotation vRotArc       = llEuler2Rot( <30.0, 0.0, 0.0> * DEG_TO_RAD );
 //-- creates a rotation constant, 30 degrees around the X axis

vector   vPosOffset     = <0.0, 1.0, 0.0>;
 //-- creates an offset one meter in the positive Y direction

vector   vPosRotOffset  = vPosOffset * vRotArc;
 //-- rotates the offset to get the motion caused by the rotation

vector   vPosOffsetDiff = vPosOffset - vPosRotOffset;
 //-- gets the local difference between the current offset and the rotated one

vector   vPosRotDiff    = vPosOffsetDiff * llGetRot();
 //-- rotates the difference in the offsets to be relative to the global rotation.

vector   vPosNew        = llGetPos() + vPosRotDiff;
 //-- finds the prims new position by adding the rotated offset difference

rotation vRotNew        = vRotArc * llGetRot();
 //-- finds rot to continue facing offset point
アプリケーションにおいて、以下の操作が行われています:
llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (vPosOffset - vPosOffset * vRotArc) * llGetRot(),
                       PRIM_ROTATION, vRotArc * llGetRot()] );
  • 上記の方法では、周回しているオブジェクトは常に中心に対して同じ側面を向いています。回転を保持する代替方法は次の通りです
llSetPrimitiveParams( [PRIM_POSITION, llGetPos() + (vPosOffset - vPosOffset * vRotArc) * llGetRot()];
vPosOffset = vPosOffset * vRotArc;

注意 これは移動操作ですので、オブジェクトをワールドの外に移動させたり、地下に埋めたり、10メートル以上移動させる場合の問題に注意してください。また、完全な軌道を得るためには、リストされたステップを繰り返す必要があります(タイマーを使用することができます)。

注意 これらはルートプリム(または好みに応じた子プリム)に適用されます。子プリムの場合、位置にはPRIM_POS_LOCALを、回転にはPRIM_ROT_LOCALまたはllGetLocalRotを使用し、回転の中心はルートに対して相対的である必要があります。

Position of Relative Point Around Rotated Object

オブジェクトの現在の向きに対して相対的なポイントを取得するには(rezzorsなどで使用されることがあります)、次のようにします。

vector   vPosOffset     = <0.0, 0.0, 1.0>;
 //-- creates an offset one meter in the positive Z direction.

vector   vPosRotOffset  = vPosOffset * llGetRot();
 //-- rotate the offset to be relative to objects rotation

vector   vPosOffsetIsAt = llGetPos() + vPosRotOffset;
 //-- get the region position of the rotated offset
アプリケーションにおいて、以下の操作が行われています:
llRezAtRoot( "Object", llGetPos() + vPosOffset * llGetRot(), ZERO_VECTOR, ZERO_ROTATION, 0 );

Normalizing a Rotation

正確性が必要な場合、正規化された回転を使用することはしばしば重要であり、必要なことさえあります。これは、各四元数の 'x'、'y'、および 'z' の値が1に等しくなるようにスケーリングすることを意味します。LSLのいくつかの操作は、これを行わないと実行時エラーが発生する場合があります。別の視点で見ると、回転を、ベクトル<1.0、1.0、1.0>に回転角を適用する方法で表現する必要があります。数学的に、回転 'Q' を正規化することは次のように計算されます。

Normalized Q = Q / Sqrt( Q.x^2 + Q.y^2 + Q.z^2 + Q.s^2)

Putting that in LSL terms:

rotation NormRot(rotation Q)
{
    float MagQ = llSqrt(Q.x*Q.x + Q.y*Q.y +Q.z*Q.z + Q.s*Q.s);
    return <Q.x/MagQ, Q.y/MagQ, Q.z/MagQ, Q.s/MagQ>;
}
Note: 正規化されていない回転を取得するLSLの唯一の方法は、llAxes2Rot/ja('相互に直交していない入力'または '異なる大きさの入力'を介して)または回転の要素を直接操作することです。他のすべてのll*関数は正規化された回転を返します。前述の例の使用により、有限の精度の制約により、正規化された回転に小さな浮動小数点エラーが導入される可能性があります。

便利なスニペット

文字列がRotationか判定

integer IsRotation(string s)
{
    list split = llParseString2List(s, [" "], ["<", ">", ","]);
    if(llGetListLength(split) != 9)//リスト長のチェックをしないと次のテストが正しく動きません
        return 0;
    return !((string)((rotation)s) == (string)((rotation)((string)llListInsertList(split, ["-"], 7))));
    //it works by trying to flip the sign on the S element of the rotation,
    //if it works or breaks the rotation then the values won't match.
    //if the rotation was already broken then the sign flip will have no affect and the values will match
    //we cast back to string so we can catch negative zero which allows for support of <0,0,0,0>
}//Strife Onizuka

rotation をRoll Pitch Yawに分割

 // LindaB Helendale
// https://wiki.secondlife.com/wiki/User:LindaB_Helendale/rot2roll_pitch_yaw
vector rot2roll_pitch_yaw(rotation R)
{
    /*
    Convert rotation to roll, pitch and yaw angles 
    (c) LindaB Helendale
    Permission to use this code in any way granted
    
    Input: rotation (quaternion) R
    Output: vector <roll,pitch,yaw> 
    
    Roll, pitch and yaw are body-related rotations (intrinsic Tait-Bryan angles): 
    first yaw to the heading, then pitch around the local Y-axis and then roll 
    around the local X-axis (nose direction). This is equivalent to world coordinate 
    rotations (extrinsic Tait-Bryan angles, or LSL Euler angles) in order roll, pitch and yaw. 
    Thus the rotation R is recovered from the roll, pitch and yaw angles by inverting 
    the order of the rotations (since in LSL they are in Z Y X or yaw, pitch, roll order):
        rotation R = llEuler2Rot(<roll,0,0>) * llEuler2Rot(<0,pitch,0>) * llEuler2Rot(<0,0,yaw>);
        
    Reference: http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
    */
    vector eulerXYZ = < llAtan2(2*(R.s*R.x+R.y*R.z),1-2*(R.x*R.x+R.y*R.y)), 
                        llAsin(2*(R.s*R.y-R.z*R.x)), 
                        llAtan2(2*(R.s*R.z+R.x*R.y), 1-2*(R.y*R.y+R.z*R.z)) >;
    return(eulerXYZ);
}

Roll Pitch Yawをrotationに変換

 // LindaB Helendale
// https://wiki.secondlife.com/wiki/User:LindaB_Helendale/rot2roll_pitch_yaw
rotation roll_pitch_yaw2rot(vector R)
{
    // convert vector <roll,pitch,yaw> to LSL rotation
    return llEuler2Rot(<R.x,0,0>) * llEuler2Rot(<0,R.y,0>) * llEuler2Rot(<0,0,R.z>);
}

定数

ZERO_ROTATION

ZERO_ROTATION = <0.0, 0.0, 0.0, 1.0>;
オイラー角の<0.0, 0.0, 0.0>に相当するrotation定数

DEG_TO_RAD

DEG_TO_RAD = 0.01745329238f;
角度(°)から乗算でラジアン角を得るときのfloat定数

RAD_TO_DEG

RAD_TO_DEG = 57.29578f;
ラジアン角から乗算で角度(°)を得るときのfloat定数