2022/02/05

2プリムでリンクの蓋を開閉

今までマーケットプレイスだけで売ってた宝箱を ベネチアのお店にも置くことにしたので この機会に今まで放置してた 2プリム蓋問題 を解決することにしました。

問題というのは 2プリムでできている宝箱の蓋をいっぺんに開閉するのに 今までは箱と蓋を別々のオブジェクトに(参照: リンクなしでも親子関係)してたのを 一つのオブジェクトでもできるようにする問題です。

千両箱と3億円ケース の蓋は よくあるドアと同じで 1プリムの箱の中心をヒンジにして削れば角度を変えるだけなのでわりと楽です。
でも宝箱の蓋は変形して削った箱(中心をヒンジに→角度だけでOK)と半分の円筒(中心をヒンジにはできない→角度も位置も変更)の組み合わせなのでちょっとめんどう。
なだけでなく角度を変えたり移動するスクリプト: llSetRot(), llSetPos() は 0.2秒停止するという謎なことが起こって そのままだと部品がバラバラに動くことになります。

解決策はスクリプトでも llSetLinkPrimitiveParamsFast() を使うことでした。
Fast と書いてあるだけに止まったりはしないんです!

こんな感じ:

list PrimPosLooks = [ // プリム名, 閉じたローカルの位置,向き, 開いた位置,向き
  "top", <-0.2, 0, 0.15>,<0,0,0>, <-0.2, 0, 0.15>,<0,-60,0>,
  "cap", <0, 0, 0.15>,<90,0,0>, <-0.1, 0, 0.32321>,<90,0,60>
]; // 位置:<x,y,z> メートル, 向き:<x,y,z> 度で表した回転

integer setPosRot(integer open)
{ // open:FALSE/0 →閉じる, TRUE/1 →開く
  string name = llGetObjectName(); // プリムの名前
  integer i = llListFindList(PrimPosLooks,[name]); //
  if (i<0 || LinkNumber<2) return -1; // もし何か間違ってたら脱出
  i = i+1 + open*2; // データの場所を計算
  vector pos = llList2Vector(PrimPosLooks,i); // 位置
  vector look = llList2Vector(PrimPosLooks,i+1); // 向き
  rotation rot = llEuler2Rot(look*DEG_TO_RAD); // 回転
  llSetLinkPrimitiveParamsFast(LinkNumber, // リンク番号
    [PRIM_POS_LOCAL,pos, PRIM_ROT_LOCAL,rot]); // 位置と回転
  return open;
}

宝箱はベネチア店の階段を上がった最上階 鉄格子の中にあります(といっても誰でも開けられる鉄格子なので雰囲気だけ)。