LlSetKeyframedMotion/ja

From Second Life Wiki
Jump to navigation Jump to search

要約

関数: llSetKeyframedMotion( list keyframes, list options );

オブジェクトが従うべき位置、方向、およびタイミングのリストを指定します。オブジェクトはシミュレータによってこれらのキーフレーム間を滑らかに移動します。

他の非物理またはキーフレーム化されたオブジェクトとの衝突は無視されます(スクリプトイベントは発生せず、衝突処理は行われません)。物理オブジェクトとの衝突は計算され報告されますが、キーフレーム化されたオブジェクトはそれらの衝突の影響を受けません(ただし、物理オブジェクトは影響を受けます)。

• list keyframes 次の形式のストライドされたキーフレームリスト:

各キーフレームは、オブジェクトの前の変換に対して相対的に解釈されます。時間値は1/9秒以上である必要があります。たとえば、次のキーフレームのリストを考えてみてください: [<0, 0, 10>, ZERO_ROTATION, 5, <0, 0, 0>, ZERO_ROTATION, 5, <0, 0, -10>, ZERO_ROTATION, 5] これにより、オブジェクトは5秒間で上に10m移動します。その後、5秒間その場にとどまり、さらに別の5秒間で10m下に移動します。

空のリストは現在再生中のキーフレームアニメーションを終了します。

• list options 修飾子および将来のオプション

仕様

以下のフラグは options リスト内でサポートされます:

  • KFM_MODEの後にKFM_LOOPKFM_REVERSEKFM_FORWARD、またはKFM_PING_PONGのいずれかを指定すると、再生モードが指定されます。KFM_FORWARDがデフォルトです。キーフレームリストが提供されるときに指定する必要があります。
  • KFM_DATAの後にKFM_TRANSLATIONおよびKFM_ROTATIONのビットごとの組み合わせ。デフォルトでは回転と変位の両方が提供される必要があります。片方だけを指定する場合は、キーフレームリストに変位または回転のいずれかを含める必要があります。キーフレームリストが提供されるときに指定する必要があります。
  • KFM_COMMANDの後にKFM_CMD_STOPKFM_CMD_PLAYKFM_CMD_PAUSEのいずれかを指定すると、再生コマンドが指定されます。STOPはアニメーションを一時停止し、最初からリセットします。PAUSEはアニメーションをリセットせずに一時停止します。PLAYは一時停止または停止したアニメーションを再開します。

KFM_COMMANDがオプションリストで提供される場合、それはリスト内で唯一のオプションでなければならず、キーフレームリストを設定する同じ関数呼び出しで指定することはできません。

インターリージョンの移動はサポートされています。オブジェクトをsimの境界外に配置するターゲットキーフレームを指定するだけで、simの境界を越えます。これにより、オブジェクトが2つのリージョンの間にあるときにアニメーションが一時停止するかのような効果が得られますが、ビューアはその動きを補間し続けます。それはsimの境界にジャンプし、同じ速度で続行しますが、simクロッシングによりウェイポイント間の時間が増加します。これをシステムに組み込む際はこれを考慮してください。

キーフレーム化されたモーションは、スクリプトが呼び出されたスクリプトに制限されず、リンクセット内の複数のスクリプトを使用して同じキーフレーム化されたモーションを制御、一時停止、または再開することができます。キーフレームリストを提供するためのオリジナルのキーフレームリストを渡す必要はありません。キーフレームリストの代わりに空のリストを渡し、オプションリストにKFM_COMMANDを指定してコマンドを指定します。

オプション フラグ 追加パラメータ 説明
KFM_COMMAND ] 0 [ integer command ] 設定するコマンド
KFM_CMD_PLAY 0 ?
KFM_CMD_STOP 1 ?
KFM_CMD_PAUSE 2 ?
KFM_MODE ] 1 [ integer mode ] 設定する再生モード初期値は KFM_FORWARD
KFM_FORWARD 0 ?
KFM_LOOP 1 ?
KFM_PING_PONG 2 ?
KFM_REVERSE 3 ?
KFM_DATA ] 2 [ integer fields ] ...を設定する初期値は (KFM_ROTATION | KFM_TRANSLATION)
KFM_ROTATION 0x1 ?
KFM_TRANSLATION 0x2 ?

警告

  • この機能は添付ファイルでは機能しません。
  • この機能は非物理オブジェクトにのみ呼び出すことができます。将来的には物理オブジェクトもサポートされる可能性がありますが、これはオブジェクトが目標位置に到達するのを妨げる可能性があるため、複雑です。
  • キーフレームモーションがアクティブな間、リンクセット内の任意なprimを移動させるためにスクリプトを使用することはできません。必要な場合は、KFM_CMD_PLAYを使用して一時停止し、完了したら再開してください。#Example
  • アバターとの衝突はオブジェクトの角運動に影響を与え、最終的な回転に到達しないかもしれません。
  • この機能はリンクセットのルートprimでのみ呼び出すことができます。
  • この機能を使用するには、リンクセットがPrim Equivalencyシステムを使用している必要があります。ただし、キーフレーム化されたオブジェクトはダイナミクスペナルティを受けず、最大で64の物理重量を持つことができます。
  • Second Lifeの最大速度である250メートル/秒を超える線形速度はDEBUG_CHANNELでエラーが発生します。
  • llSetKeyframedMotionはフレーム単位で実装されており、実際の時間ではありません。期待される位置と回転からのドリフトを避けるためには、1/45の整数倍の時間を使用してください。たとえば、20.0/45.0、40.0/45.0、90.0/45.0などです。フォーラムスレッド KFMはデルタタイムが0.1秒よりも大きい必要があると主張していますが、実際にはわずかに0.1を超えるデルタタイムはDEBUG_CHANNELでエラーを発生させます。テストでは、最小のデルタタイムは約6/45(.13333)秒です。
    • 自然なドリフトはまだ発生する可能性があります。最良の結果を得るためには、moving_endを使用してアニメーションが終了したときに確認し、llSetPosでターゲットの位置を確認するか、at_targetまたはat_rot_targetを使用できます。
  • 動的オブジェクトと同様に、この機能を使用して移動するオブジェクトは、適切な権限を持つアバター(オブジェクトの所有者、乗客など)によって選択されると一時停止します。そのようなアバターがオブジェクトを選択解除すると、動きが再開されます。たとえオブジェクトがKFM_CMD_PAUSEを使用して一時停止していた場合でもです。
  • キーフレームモーションはある意味でprim propertyです。KFM_LOOPまたはKFM_PING_PONGが開始されると、モーションスクリプトが削除された後も保存されます。つまり、primはそのモーションを継続します。テイクやコピーにも耐えます。サーバー再起動にも耐えます。
  • リージョン間の移動は完璧ではありません。曲がったパスの多いKey Frameリストを使用してsim 1からsim 2に移動すると、クロス上で顕著なエラーが発生し、KFM_MODE,KFM_REVERSEで逆転されると、オブジェクトはsim 2に留まり、sim 1に戻りません。
All Issues ~ Search JIRA for related Bugs

サンプル

KFMオブジェクトは新しいPrim Equivalencyシステムを使用する必要があります。これを実現するための一つの方法は、物体がその物理形状にConvex Hullを使用していることを確認することです。 (主に新しいprimはこのような回避策が必要です。メッシュオブジェクトは常に新しいPrim Equivalencyシステムを使用します。)

llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);

これは簡単な前後または「ピンポン」モーションの例で、位置と時間のみを使用しています。

llSetKeyframedMotion([<0.0, 0.0, 10.0>, 5, <0.0, 0.0, -10.0>, 5], [KFM_DATA, KFM_TRANSLATION, KFM_MODE, KFM_PING_PONG]);

この例には位置、回転、および時間が含まれています。

llSetKeyframedMotion(
    [<0.0, 0.0, 10.0>, llEuler2Rot(<90, 45, 180> * DEG_TO_RAD), 5,
     <0.0, 0.0, -10.0>, llEuler2Rot(<270, 225, 360> * DEG_TO_RAD), 5],
    [KFM_MODE, KFM_REVERSE]);

一時停止-再生

KFMオブジェクトの位置を更新する必要がある場合、KFMを一時停止してから再開する必要があります。

llSetKeyframedMotion([],[KFM_COMMAND, KFM_CMD_PAUSE]);
// Modify prim positions here
llSetKeyframedMotion([],[KFM_COMMAND, KFM_CMD_PLAY]);

サンプルスクリプト - キーフレームド フォロワー

特定の状況では、回転が正規化されていないと実行時エラーが発生する場合があります。このスクリプトは、正規化された目標回転を使用してフォロワーを作成するためにllKeyframedMotionを使用する方法を示しています。例えば、車両の後ろにあるカートなどを考えてください。

key scriptedObjectToFollow = "daf4847b-967d-bff6-69c0-fd7022241be7";
integer isSensorRepeatOn;

rotation NormalizeRotation(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>;
}

default
{
    state_entry()
    {
        llSetLinkPrimitiveParamsFast(LINK_ROOT, [
            PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX,
            PRIM_LINK_TARGET, LINK_ALL_CHILDREN,
            PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_NONE
        ]);
    }

    touch_start(integer total_number)
    {
        isSensorRepeatOn = !isSensorRepeatOn;

        if (isSensorRepeatOn)
        {
            llSay(PUBLIC_CHANNEL, "Sensor repeat switched on!");
            llSensorRepeat("", scriptedObjectToFollow, SCRIPTED, 10.0, PI, 0.3);
        }
        else
        {
            llSensorRemove();
        }
    }

    sensor(integer num_detected)
    {
        vector ownPosition = llGetPos();
        rotation ownRotation = llGetRot();
        vector detectedPosition = llDetectedPos(0);
        rotation detectedRotation = llDetectedRot(0);

        vector kfmPosition = (detectedPosition - ownPosition) + <-1.0, 0.0, 0.2> * detectedRotation;
        rotation kfmRotation = NormalizeRotation(detectedRotation / ownRotation);
        llSetKeyframedMotion([kfmPosition, kfmRotation, 0.15], []);
    }
}

8つのキーフレームでのユニバーサルヒンジモーション

このスクリプトは、ボックスprimをprimのY軸に平行なエッジを中心に回転させます。
このスクリプトはどんなprimの向きに対しても機能します。
1フレームあたりの最小受け入れられる時間は1/9秒=0.11111111秒であり、0.1秒ではありません。

float angleEnd=PI_BY_TWO;
float speed=0.2; // m/S
float steps=8.0; // number of Key Frames
float step=0.0;
list KFMlist=[];
vector V;
integer open=TRUE;
vector basePos;
rotation baseRot;

float motion_time( float mt)
{
    mt = llRound(45.0*mt)/45.0;
    if ( mt > 0.11111111 ) return mt;
    else return 0.11111111;
}

default
{
    state_entry()
    {
        llSetMemoryLimit(0x2000);
        llSetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]);
        basePos = llGetPos();
        baseRot = llGetRot();
        vector v1 = 0.5*llGetScale()*llGetRot();
        rotation deltaRot = llEuler2Rot(< 0.0, angleEnd/steps, 0.0>);
        while ( step < steps )
        {
            V = v1*llAxisAngle2Rot(llRot2Left(llGetRot()), angleEnd*step/steps);
            V = v1*llAxisAngle2Rot(llRot2Left(llGetRot()), angleEnd*(step+1.0)/steps) - V;
            KFMlist += [V, deltaRot, motion_time(llVecMag(V)/speed)];
            step += 1.0;
        }
    }
    touch_end( integer n)
    {
        llSetKeyframedMotion( [], []);
        if ( open )
        {
            llSetPrimitiveParams([PRIM_POSITION, basePos, PRIM_ROTATION, baseRot]);
            llSetKeyframedMotion( KFMlist, []);
        }
        else
        {
            llSetKeyframedMotion( KFMlist, [KFM_MODE, KFM_REVERSE]);
        }
        open = !open;
    }
    on_rez( integer n) { llResetScript(); }
}

プリムの位置、回転、および/またはサイズを編集した後、モーションを更新するためには、スクリプトをリセットする必要があります。

連続スピン

以下の例は、primがConvex Hullに設定されており非物理的であると仮定して、Z軸を中心に連続して回転するようにするためのllTargetOmega(<0.0,0.0,1.0>,PI,1.0)を使用するのと同じことを行います。

integer gON;

default
{
    touch_start(integer total_number)
    {
        gON = !gON;
        if (gON)
        {
            // Make repeated rotations of PI/2 radians, each taking 0.5 seconds
            llSetKeyframedMotion([llEuler2Rot(<0.0,0.0,PI/2>), 0.5],[KFM_DATA,KFM_ROTATION, KFM_MODE,KFM_LOOP]);
        }
        else
        {
            llSetKeyframedMotion([],[]);
        }
    }
}

追加の例

注意点

潜在的な利用シーン:

  • エレベーター
  • 動くプラットフォーム
  • 列車/固定軌道の車両
  • 動くドア/壁/ゲート
  • 風車やその他の機械

対象の座標系: 平行移動はグローバル座標で、回転はローカル座標で行われます

  • 例: X軸上の移動は、オブジェクトがどのように回転しているかに関係なく、グローバル座標、リージョンX軸に沿ってオブジェクトを移動させます
  • 例: X軸を中心に回転させると、オブジェクトはそのローカル座標、prim X軸を中心に回転します。オブジェクトの回転に関係なくです
  • グローバル座標系でオブジェクトが回転していない場合、その違いは気づかれません

特記事項

経緯

Date of Release 09/11/2011

All Issues

~ Search JIRA for related Issues
   llSetKeyframedMotion() does not support inter-region motion
   Option for viewer-only llSetKeyframedMotion() functionality
   Curve Interpolation for llSetKeyframedMotion()
   Bezier Curve Support for llSetKeyframedMotion()
   KFM_STRICT_TIMING for llSetKeyframedMotion()
   KFM_SYNC_TIME - Synchronised Timing for llSetKeyframedMotion()

Signature

function void llSetKeyframedMotion( list keyframes, list options );
この翻訳は 原文 と比べて古いですか?間違いがありますか?読みにくいですか?みんなで 修正 していきましょう! (手順はこちら)
この項目はあなたにとって参考にならない項目ですか?もしかしたらLSL Wikiの関連した項目が参考になるかもしれません。