コメントやトラックバック、FriendFeedやTwitterでのツッコミは大歓迎です!
携帯用 by Google

Search

Profile & Feeds

GOTTi
GOTTi@iNNX
FriendFeed - gotti twitter - hidenorigoto flickr - GOTTi mixi - hidenorigoto facebook - hidenorigoto last.fm - hidenorigoto
最近は、PHPのMVCフレームワーク「symfony」関連の活動と、多治見IT勉強会などをやっています。
Googleプロフィール
ブログへのコメントやツッコミ、twitterやFriendFeedでのreplyなどお気軽にお願いします!

Latest Posts

369件のエントリ

Category

iNNX Links

Other Links

Friends Links

240 件中 1 ~ 5 件目 (全 48 ページ)

LSL Convention Japan 2009 閉幕しました

2009/10/19 02:05 add to hatena hatena detail hatena detail

今年のLSLCONが無事終わりました。

振り返ればいろいろ準備不足な点がまだまだ浮かんでしまいますが、それでも、私は今年のLSLCONで自分が担当した作業に、自信を持って合格点をつけたいです。

このようなイベントは、決して誰か一人の人間が努力して運営できるものではありません。

特にLSLCONでは、多くの展示作品の出品に支えられている部分が大きいです。


運営メンバーだけでなく、より多くの人が、「来年もLSLCONがあるといいよね」と考え、行動することで、このイベントが継続していくはずです。

私は、(セカンドライフが続いている限り) LSLCONが続いて欲しいなと強く願っています。

2009/10/19 02:05 add to hatena hatena detail hatena detail コメント

LSLCONって結局何がしたいの?

2009/10/02 05:37 add to hatena hatena detail hatena detail
Snapshot_001

10月になりました。私にとっては「LSL Conventionの月」です(笑

2007年に始まったこのイベントも今年で3回目です。


私は、昨年に続き今年も運営っぽい位置でこのイベントに参加しています。昨年あたりからの強いSL逆風?で、「今年は展示作品の応募は寂しくなるんじゃないかなぁ」などと弱気な予測を立てていたのですが、蓋を開けてみると60作品以上も応募があり、まだまだセカンドライフでスクリプトを書いている人はたくさんいるんだなぁと驚いていたりもします。

さて、そんなLSLCONですが、スクリプターさんから「前に見に行ったけど驚くようなスゴイ作品はなかった」というような声をたまーに耳にすることがあります。展示への出品をお願いしても、そういった理由で参加していただけない方などもいらっしゃるようで、ちょっと残念に思ったりしていました。(私たちの説明がまだまだ至らないという理由もあると思います)

ただ、正直に書きますと、私自身も2007年に第1回LSLCONのただの観客だった頃は、同じような感想を持っていました。


実際のところ、一通り「LSLでできること」が分かってしまうと、スクリプト作品を見て「そんなことができるのか!」と驚くことはほとんどなくなり、「あー、これはあの関数を使ってごにょごにょ」と作り方まで分かってしまうんですよね。そして、「自分にも作れるし、たいしたことないなぁ」という感想ばかりになってしまいがちです。


では何故、私や他の運営スタッフが自分たちの多大な時間を割いてこのイベントを続けているのでしょうか。


LSLではいろいろな事ができるので、展示作品はいくつかのカテゴリーに分かれています。例えば「アミューズメント」だったり「ツール」だったり。そして、特定の分野、例えば「乗り物」に特化したスクリプトばかりを書いている人もいれば、全般的にいろいろやっていたりする人もいたり、アニメーション関連ばかりをやっている人もいたりします。そのようないろいろな人の作品が一堂に会するのがLSL Conventionの展示です。

特定の分野に特化したスクリプトばかりを書いている人には、その分野での何らかのノウハウだったり、こだわりなどがあったりします。また、スクリプトを使うユーザーも様々で、分野によってはユーザーが「使いやすい」「一般的」と捉える機能に差があったりもします。 

このような、機能的にただLSLの関数などを組み合わせて機能を実現するという部分以外のノウハウだったり、目線や価値観などを、得ようと思う人にとってはたくさん得られるのがLSL Conventionの展示(およびイベントそのもの)だと私は考えています。


このように書くと、何かを求めているスクリプターにとっては「不親切なイベント」なのかもしれませんね。
でも、「受け身のままでは楽しめない」という点は、Second Life住人なら頷いていただける方が多いんじゃないかと私は思っています。


スクリプトを書いている方なら、是非とも会場に足を運んでいただいて、スクリプター同士で苦労話に花を咲かせたりしてみてはいかがでしょうか?


そんなLSL Convention Japan 2009は、10月10日(土)からです! 

お楽しみに!


※「運営に参加するともっと楽しいよ」という話もいつか書きます・・・いつか・・・;;


関連ブログ・リンク:


2009/10/02 05:37 add to hatena hatena detail hatena detail コメント

サーバー1.27で、いよいよHTTP-INがメイングリッドに

2009/07/11 10:49 add to hatena hatena detail hatena detail

セカンドライフのメイングリッドのサーバー(SIM)のバージョンアップが今月行われて、1.27になりますが、このバージョンアップにはLSL関連で久々に大きな機能追加が行われています。それが「HTTP-IN」と呼ばれている機能です。


HTTP-INは何か?というのを端的に説明すると、「これまでのXML-RPCをHTTPでできるようにした」ものです。

具体的には、以下のようなことができるようになります。

  • プリムに割り当てられたURLを使用してアクセスする
    • Second Life内部ではLSLのllHTTPRequestを使用してアクセス可能
    • Second Life外部からも同様にアクセス可能
  • URLにアクセスがあると、スクリプトに「http_request」イベントが発生します。
    • このイベント内で何らかのスクリプト処理を行って、レスポンスとして返すことができます。
    • 例えば、イベントが発生した時点でセンサーを起動して、その時点で周囲にいるアバター名の一覧をレスポンスとして返すことなどもできます。

HTTP-INで割り当てられるURLは、例えば以下のようなものです。

このURLの「sim3893」という部分は、リージョンのホストに対応しています。つまり、SIMが変わればURLも変わります。

実際には、URLのハンドリングがちょっと難しいので、そこを理解しておかないと利用するのが難しそうです。以下に、URLが無効になってしまう例を挙げます。

  • スクリプトがリセットされた時
    • スクリプトを書き換えて保存した場合も同様です
    • state_entryイベントで処理します。
  • スクリプトの入ったプリム/オブジェクトをtakeした時
    • takeした瞬間に無効になります。再度rezしてもダメです。
    • on_rezイベントで処理します。
  • リージョンが再起動した場合
    • changedイベントのCHANGED_REGION_STARTイベントが発生します。
  • アバターが身につけているオブジェクトの場合、テレポートしたりSIMを超えた場合
    • changedイベントのCHANGED_REGIONまたはCHANGED_TELEPORTイベントが発生します。

このように、URLが頻繁に変わってしまいます。

以下、HTTP-IN関連で追加された関数・イベント・定数の一覧です。

  • llRequestURL HTTP-IN用のURL割り当てを要求します。URLが割り当てられるとhttp_requestイベントが発生します。
  • llRequestSecureURL llRequestURLと同様ですが、HTTPSプロトコル用のURLが割り当てられます。
  • llReleaseURL 割り当てられたURLを明示的に解放します。
  • http_request URL割り当て完了時、およびURLへのアクセスがあった場合に発生します。
  • llHTTPResponse HTTPリクエストに対して、レスポンスを返します。
  • llGetHTTPHeader HTTPリクエストのいくつかのヘッダを取得します。
  • llGetFreeURLs スクリプトで割り当て可能なURLの数を取得します。
  • CHANGED_REGION_START リージョンが再起動したときに発生するchangedイベントのフラグです。


現在はまだNew Script SIMはバージョンアップされていないようなので、今日のスクリプターの会ではどこかバージョンアップされているSIMに移動して、HTTP-INをアレコレ試してみたいですね。


関連リンク:



2009/07/11 10:49 add to hatena hatena detail hatena detail コメント

ドアのスクリプトサンプル - 滑らかに開閉するドア

2009/07/05 11:41 add to hatena hatena detail hatena detail

さて、ドアシリーズもこのエントリで多分最後ですが、先のエントリのドアを「滑らかに(ゆっくり)開閉する」バージョンを作成してみました。

どういった動きなのかは、以下のムービーをご確認ください。

スクリプトは、以下のようになっています。タイマーによるドアの動き制御が追加されています。また、それに合わせてステート分割も行いました。

/////////////////////////////////////////////////////////////////////
//  ドアのサンプルスクリプト(door3.lsl)
//  タッチしたアバターの位置によって開く向きが変わる
//  滑らか開閉バージョン
//  Released into the public domain by Hidenori Glushenko
/////////////////////////////////////////////////////////////////////
//  初めに「door_init.lsl」スクリプトでプリムを変形させておいてください。
/////////////////////////////////////////////////////////////////////
rotation    DOOR_ROT_ORG;                       //  ドアの基準回転
float       DOOR_DIV_EULER = 150.0;             //  ドアの開閉角度
float       DOOR_OPEN_SEC = 10.0;               //  ドアが開いている時間(秒)
float       DOOR_MOVE_TARGET;
integer     TIMER_COUNT;
integer     TIMER_MAX = 40;                     //  ドアの開閉速度
                                                //  大きいとゆっくり
default {
    state_entry() {
        llSetBuoyancy(1.0);
        llMinEventDelay( 0.01 );
        llSetStatus(STATUS_PHANTOM, FALSE);
        llSetStatus(STATUS_BLOCK_GRAB, TRUE);
        state   DoorClose;
    }
}
 
state   DoorClose {
    touch_start(integer total_number) {
        DOOR_ROT_ORG = llGetRot();
 
        //  タッチしたアバターの位置関係を調べる
        vector av_offset = (llDetectedPos(0)-llGetPos())/DOOR_ROT_ORG;
        float av_offset_z = av_offset.z;
 
        //  位置関係に応じた回転を計算
        DOOR_MOVE_TARGET = (av_offset_z/llFabs(av_offset_z))
                            *DOOR_DIV_EULER;
        state DoorOpen;
    }
}
 
state   DoorOpen {
    state_entry() {
        TIMER_COUNT = 0;
        llSetTimerEvent(0.05);
        llSetStatus(STATUS_PHANTOM, TRUE);
    }
 
    touch_start(integer total_number) {
        //  タッチされたらタイマー間隔を戻す
        llSetTimerEvent(0.05);
    }
 
    timer() {
        rotation rot;
        integer count = ++TIMER_COUNT;
 
        //  閉まる時用の変数補正
        if (TIMER_COUNT > TIMER_MAX) {
            count = 2*TIMER_MAX - count;
        }
 
        //  閉まり始めた時の処理
        if (TIMER_COUNT == TIMER_MAX + 1) {
            llSetStatus(STATUS_PHANTOM, TRUE);
            llSetTimerEvent(0.05);
        }
 
        //  現在のカウンタ変数から、角度を求める
        float x = PI_BY_TWO*count/(float)TIMER_MAX;
        float new_rot_euler = DOOR_MOVE_TARGET * llPow(llSin(x), 2.0);
        llRotLookAt(rot = (llEuler2Rot(<0.0,new_rot_euler,0.0>
            *DEG_TO_RAD))*DOOR_ROT_ORG,1.0,1.0);
 
        //  開ききったら止める
        if (TIMER_COUNT == TIMER_MAX) {
            //  タイマー間隔を切り替える
            llSetTimerEvent(DOOR_OPEN_SEC);
            llSleep(0.2);
            llSetStatus(STATUS_PHANTOM, FALSE);
            llSetStatus(STATUS_PHYSICS, TRUE);      //  角度反映処理
            llSetStatus(STATUS_PHYSICS, FALSE);     //  角度反映処理
            llSetRot(rot);
 
        //  閉まったら状態を変更してステート遷移
        } else if (TIMER_COUNT >= (TIMER_MAX*2)) {
            llSleep(0.2);
            llSetStatus(STATUS_PHYSICS, TRUE);      //  角度反映処理
            llSetStatus(STATUS_PHYSICS, FALSE);     //  角度反映処理
            llSetRot(DOOR_ROT_ORG);
            state DoorClose;            
        }
    }
 
    state_exit() {
        llSetStatus(STATUS_PHANTOM, FALSE);
        llSetTimerEvent(0.0);
    }
}

ドアの開閉の動きは、llRotLookAt関数を使用しています。

この関数を使用すると、オブジェクトを(ディレイなく)回転させることができます。(回転がllTargetOmegaと同じようにビューア側での処理になるため)
ただし、これまたllTargetOmegaと同じように、サーバー上でオブジェクトが回転しているわけではないため、開いた状態をシミュレータ側に反映させる処理が必要になります。


また、現在はドアの動きをsinの2乗(llPow(llSin(x), 2.0) (xは0~π/2)という計算式を使っていますが、ここを変更すると、開く動きを変えられます。


タイマーでドアの角度を処理していく部分は、いろいろな書き方が考えられる部分で、もっとうまいやり方がありそうです。「こうするのがいい」というのがあれば、是非教えてください!


関連エントリ(ドアシリーズ):


2009/07/05 11:41 add to hatena hatena detail hatena detail コメント

プリムに座っているアバターの位置アレコレ

2009/07/04 22:37 add to hatena hatena detail hatena detail

さて、前のエントリで「タッチイベントで検出したアバターの位置(=llDetectedPos)が見た目とずれている」ということを書きましたが、実際これはどういった法則でずれているのか考えてみました。



実はこれ、私が以前ChairKitを作成した時に調べていたことと結局同じでした(笑)

結論としては次のようになっています。

  • プリムにsitしたアバターのリージョン座標・・・座標A
    • sittargetの座標を基準として計算されます。
    • sittargetの座標より「上」にずれます。
    • llGetObjectDetailsでアバターの座標を取得すると、この座標が取得できます。
    • タッチイベントのあるオブジェクトにこのアバターがタッチすると、llDetectedPosで取得できる座標はこの座標になります。
  • sittargetの座標・・・座標B
    • プリムにsittargetを指定した場合は、その座標です。
      (リージョン座標としては、プリムのリージョン座標+sittarget)
    • 見た目では、sittargetの位置よりも後ろにアバターがずれます。
      このずれの計算式はまだ未確認ですが、このエントリで挙げる法則を少し改良すれば、座っているアバターのほぼ腰の位置を求めることは可能かと思います。


さて、今回のテスト用に次の3つのスクリプトを用意しました。

スクリプトA:タッチされたアバターの座標へ移動する(llDetectedPos)

default {
    touch_start(integer total_number) {
        vector pos;
        llSetPos(pos = llDetectedPos(0));
        llOwnerSay((string)pos);
    }
}

スクリプトB:設定されているsittargetの位置へ移動する(オブジェクト名、sittargetのvectorは固定です)

default {
    touch_start(integer total_number) {
        llSensor("chair_base", NULL_KEY, PASSIVE | SCRIPTED, 10.0, PI);
    }
    sensor(integer num_detected){
        vector pos;
        llSetPos(pos = (llDetectedPos(0) + <0.2,0,0.5>*llDetectedRot(0)));
        llOwnerSay((string)pos);
    }
}

スクリプトC:タッチされたアバターの座標からsittargetを逆算して、求めた位置へ移動する

vector detectedPos2SitTarget(key avatar, vector pos, rotation rot){
    vector tp = llGetAgentSize(avatar);
    pos = (pos + (llRot2Up(rot) * tp.z * 0.02638) - (llRot2Up(rot) * 0.4));
    return pos;    
}
 
default {
    touch_start(integer total_number) {
        key avatar = llDetectedKey(0);
        vector pos = detectedPos2SitTarget(
            llDetectedKey(0), llDetectedPos(0), llDetectedRot(0));
        llOwnerSay((string)pos);
        llSetPos(pos); 
    }
}


このようなスクリプトを赤、黄、青の球のプリムに入れて、いろいろな状態でタッチしてみました。

以下の実験では、座っているプリムに <0.2, 0.0, 0.5> というsittargetが設定されています。



黄色(sittargetの位置へ移動)は、当然ですが、sittargetの位置へそのまま移動します。
赤は、sittargetの黄色ボールより上の位置に移動します。真上から見た図で、X、Y座標が同じであることが分かります。

この状態から、青いボールにタッチして移動させます。

青いボールにタッチすると、黄色いボールと中心が重なる位置に移動します。

座っているプリムの位置を変えたり、アバターのアニメを変えたり(sittargetの位置は変えていません)、タイニーアバターになってみたりしても、この3つのボールの位置関係は同じままです。


■座標Aと座標Bの変換式

では、座標Aと座標B、つまり赤いボールと黄色いボールの間の座標の関係および変換はどのようになっているのでしょうか。ChairKitの作成段階(その前段階のバージョン1を作っていた頃に)いろいろ調べてたどり着いたのが、PWikiの次のページでした。

上記ページに、Strife Onizukaさんが作成した次のようなコードが掲載されています。

GetSitTarget

list GetSitTarget(integer prim, key av)
{//WARNING: llGetObjectDetails can introduce an error that goes as far as the 5th decimal place!
 //This is highly unlikely to be ever noticed unless compounded over time.
 //Do not use while moving (like in a moving vehicle)!!!
    vector tp = llGetAgentSize(av);
    if(tp)
    {
        if(prim == LINK_THIS)//llGetLinkKey doesn't like LINK_THIS
            prim = llGetLinkNumber();
 
        list details = [OBJECT_POS, OBJECT_ROT];
        rotation f = llList2Rot(details = (llGetObjectDetails(llGetLinkKey(prim)
          , details) + llGetObjectDetails(av, details)), 1);
        rotation r = llList2Rot(details, 3) / f;
 
        return [((llList2Vector(details, 2) - llList2Vector(details, 0)) / f)
          + (llRot2Up(r) * tp.z * 0.02638) - <0.0, 0.0, 0.4>, r];
    }
    return [];
}//Written by Strife Onizuka

これが、「sitしているアバターのローカル座標から、(概算の)sittargetを取得する」関数です。

この関数ではローカル座標(sittargetは設定するプリム基準)を計算しているので分かりづらいですが、まとめてさらに変形すると以下のような計算式になっています。

  [sittargetの座標] = [検出したアバターの座標]
        + llRot2Up([アバターの回転]) * [アバターの身長] * 0.02638
        - llRot2Up([アバターの回転]) * 0.4

妙な定数が出てきて、正当性は何とも言えませんが、SSで見るように、実際にsittargetの位置とほぼ一致します。

ただ、標準的な人間アバターであればこの計算式はほぼ正しいようですが、タイニーアバターになった場合、やや誤差が大きくなります(下のSS参照。5cmほどずれています)

つまり、アバターの身長に依存する部分が上の式では単純な1次関数ですが、もう少し複雑な計算になっているのだと思われます。
が、この計算式でも現時点ではほとんど問題が無いと思います。
(PWikiに長い間掲載されていて、文句などがついていないと言うこともあります)

時間があれば、ここから「(概算)腰の位置」を求める関数も作っておこうかと思いますが、今日はここで力尽きました・・・・。


2009/07/04 22:37 add to hatena hatena detail hatena detail コメント