2016年09月12日
他人が座っているプリムの情報取得/REZした物の情報取得
llGetObjectDetails()が強化されていることに今更気づきましたが。。(笑)、表題の事がようやっと出来る様になりました。
key _sitRootKey=llList2Key(llGetObjectDetails(アバターのuuid,[OBJECT_ROOT]),0);
if (_sitRootKey!=アバターのuuid)
{
何かする
}
とやって、llGetObjectDetails()の返す答えと元のアバターのuuidが異なる事を確認すると、違っていた場合に戻ってきたkeyがアバターが座っている物体のルートのUUIDになります。
また、
key _rezzer=llList2Key(llGetObjectDetails(llDetectedKey(0),[OBJECT_REZZER_KEY]),0);
とか唱えてやるとプリムをREZした親のUUID(Rezzerならそれ、アバターならアバターの)を取れます。Rezzerスクリが子プリム入りの場合は子プリムのUUIDが帰ってくるので、実際上は、
key _rezzer=llList2Key(llList2Key(llGetObjectDetails(llDetectedKey(0),[OBJECT_REZZER_KEY]),0),[OBJECT_ROOT],0);
と二発重ねて使う事が多いだろうと思いますが、これもかなり強力な機能強化だと思います。
key _sitRootKey=llList2Key(llGetObjectDetails(アバターのuuid,[OBJECT_ROOT]),0);
if (_sitRootKey!=アバターのuuid)
{
何かする
}
とやって、llGetObjectDetails()の返す答えと元のアバターのuuidが異なる事を確認すると、違っていた場合に戻ってきたkeyがアバターが座っている物体のルートのUUIDになります。
また、
key _rezzer=llList2Key(llGetObjectDetails(llDetectedKey(0),[OBJECT_REZZER_KEY]),0);
とか唱えてやるとプリムをREZした親のUUID(Rezzerならそれ、アバターならアバターの)を取れます。Rezzerスクリが子プリム入りの場合は子プリムのUUIDが帰ってくるので、実際上は、
key _rezzer=llList2Key(llList2Key(llGetObjectDetails(llDetectedKey(0),[OBJECT_REZZER_KEY]),0),[OBJECT_ROOT],0);
と二発重ねて使う事が多いだろうと思いますが、これもかなり強力な機能強化だと思います。
2011年09月21日
llCastRay()実装
されたみたいですね。
和訳がまだないようですので簡単にまとめておきます。
リージョン座標startからendを結ぶ直線上を調査して、検出されたオブジェクト、アバター、地面等について、optionsで指定された属性とUUIDと座標をlistで返します。
また、戻りリストの末尾はエラーコードまたは検出された物の数となります。
末尾の数(integer)が負の値の場合は、以下の意味となります。
RCERR_UNKNOWN(-1)
理由が分かりませんがエラーです。バグレポートをリンデンに送りましょう。
RCERR_SIM_PERF_LOW(-2)
SIMが重すぎて実行できませんでした。
RCERR_CAST_TIME_EXCEEDED(-3)
地区やアバターで許されている実行用のリソースが使い切られていて実行できませんでした。
少し時間を空けると実行できるようになります。
RC_REJECT_TYPES
無視するものを以下のフラグのビット和( | )で指定できます。
RC_REJECT_AGENTS アバターを無視します
RC_REJECT_PHYSICAL 物理プリムを無視します
RC_REJECT_NONPHYSICAL 通常プリムを無視します
RC_REJECT_LAND 地面を無視します
RC_DATA_FLAGS
取得するデーターにいくつかの追加、変更を行えます。以下のフラグのビット和( | )で指定できます。
RC_GET_NORMAL 検出地点(プリムの表面で起こります)の法線ベクトル(面に垂直な単位ベクトル)を追加して返します。
RC_GET_ROOT_KEY 指定すると検出したプリムのリンクセットのルートプリムのUUIDを返します。デフォルトでは検出したプリムそのもののUUIDが返ります。
RC_GET_LINK_NUM 指定するとそのリンクセットのプリム数を追加して返します。
戻るlistの値は、
指定なし
[uuid , 検出されたプリム表面のリージョン座標 , ・・・・・・,検出した数]
RC_GET_LINK_NUMを指定
[uuid , リンク数 , 検出されたプリム表面のリージョン座標 , ・・・・・・,検出した数]
RC_GET_NORMALを指定
[uuid , 検出されたプリム表面のリージョン座標 , 法線ベクトル , ・・・・・・,検出した数]
RC_GET_LINK_NUMとRC_GET_NORMALを指定
[uuid , リンク数 , 検出されたプリム表面のリージョン座標 , 法線ベクトル , ・・・・・・,検出した数]
と並びます。検出したオブジェクトが複数の場合の、飛び石リストの並び順はstartからendへ向かう順になっているようです。(※地面にあたるとNULL_KEYが入るのでしょうか。また、地面の中からスタートするとNULL_KEYは入らずのようです。同様にプリムの中からスタートするとそのプリムは無視するのかもしれません。)
RC_MAX_HITS
ヒットさせる最大数を指定します。デフォルトは1で、出来るだけ小さい数が当然望ましいらしいです。
RC_DETECT_PHANTOM
TRUEを指定するとファントムとVolume Detectプリムを検出の対象にするようになります。
という感じみたいです。
これ、斜面でも斜面に沿って足を下ろす、ちゃんと歩行して見える乗り物が作れますね。。(笑
あんまり激しく使うとすぐエラー-3が返ってきますが・・・
和訳がまだないようですので簡単にまとめておきます。
list llCastRay( vector start, vector end, list options )
リージョン座標startからendを結ぶ直線上を調査して、検出されたオブジェクト、アバター、地面等について、optionsで指定された属性とUUIDと座標をlistで返します。
また、戻りリストの末尾はエラーコードまたは検出された物の数となります。
末尾の数(integer)が負の値の場合は、以下の意味となります。
RCERR_UNKNOWN(-1)
理由が分かりませんがエラーです。バグレポートをリンデンに送りましょう。
RCERR_SIM_PERF_LOW(-2)
SIMが重すぎて実行できませんでした。
RCERR_CAST_TIME_EXCEEDED(-3)
地区やアバターで許されている実行用のリソースが使い切られていて実行できませんでした。
少し時間を空けると実行できるようになります。
オプション設定
RC_REJECT_TYPES
無視するものを以下のフラグのビット和( | )で指定できます。
RC_REJECT_AGENTS アバターを無視します
RC_REJECT_PHYSICAL 物理プリムを無視します
RC_REJECT_NONPHYSICAL 通常プリムを無視します
RC_REJECT_LAND 地面を無視します
RC_DATA_FLAGS
取得するデーターにいくつかの追加、変更を行えます。以下のフラグのビット和( | )で指定できます。
RC_GET_NORMAL 検出地点(プリムの表面で起こります)の法線ベクトル(面に垂直な単位ベクトル)を追加して返します。
RC_GET_ROOT_KEY 指定すると検出したプリムのリンクセットのルートプリムのUUIDを返します。デフォルトでは検出したプリムそのもののUUIDが返ります。
RC_GET_LINK_NUM 指定するとそのリンクセットのプリム数を追加して返します。
戻るlistの値は、
指定なし
[uuid , 検出されたプリム表面のリージョン座標 , ・・・・・・,検出した数]
RC_GET_LINK_NUMを指定
[uuid , リンク数 , 検出されたプリム表面のリージョン座標 , ・・・・・・,検出した数]
RC_GET_NORMALを指定
[uuid , 検出されたプリム表面のリージョン座標 , 法線ベクトル , ・・・・・・,検出した数]
RC_GET_LINK_NUMとRC_GET_NORMALを指定
[uuid , リンク数 , 検出されたプリム表面のリージョン座標 , 法線ベクトル , ・・・・・・,検出した数]
と並びます。検出したオブジェクトが複数の場合の、飛び石リストの並び順はstartからendへ向かう順になっているようです。(※地面にあたるとNULL_KEYが入るのでしょうか。また、地面の中からスタートするとNULL_KEYは入らずのようです。同様にプリムの中からスタートするとそのプリムは無視するのかもしれません。)
RC_MAX_HITS
ヒットさせる最大数を指定します。デフォルトは1で、出来るだけ小さい数が当然望ましいらしいです。
RC_DETECT_PHANTOM
TRUEを指定するとファントムとVolume Detectプリムを検出の対象にするようになります。
という感じみたいです。
これ、斜面でも斜面に沿って足を下ろす、ちゃんと歩行して見える乗り物が作れますね。。(笑
あんまり激しく使うとすぐエラー-3が返ってきますが・・・
2011年01月08日
Visual C# スキャナーから画像を取り込み
あけましておめでとうございます。今年もよろしくお願い申し上げます。m(__)m
すぐ忘れるので自分用のメモです。。^^;
「スキャナで取り込んだ画像をイチイチ保存してからUPするのは面倒くさいから、勝手にするようにしてくれないか?」というワガママなRLお客様のご注文の為に。。(笑
Windows Imaging Acquisitionを参照設定に追加してから、要するに基本は以下の通りでした。。
using WIA;
・
・
public partial class Form1 : Form
{
public Form1(string[] args)
{
InitializeComponent();
(以下、なんだか色々)
}
・
・
private void scan()
{
WIA.CommonDialog dlg = new WIA.CommonDialog();
ImageFile Image = dlg.ShowAcquireImage(WiaDeviceType.ScannerDeviceType,
WiaImageIntent.ColorIntent, WiaImageBias.MaximizeQuality,
"{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}", true, true, true);
string p = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
System.IO.File.Delete(p + @"\tmp.bmp");
Image.SaveFile(p + @"\tmp.bmp");
}
}
ImageFile.SaveFile()メソッドは同名ファイルがあると例外をスローする様ですので、先に消しておくくらいでしょうか。。
LSLでところてんになった頭でたま~にWindowsアプリを作ろうとすると、ほんっとに今の環境はなんでも考えずに出来ますね。。メモリーは馬鹿みたいにありますしCPUは遊んでますし。。^^;
我ながら子供の遊びレベルです。。
すぐ忘れるので自分用のメモです。。^^;
「スキャナで取り込んだ画像をイチイチ保存してからUPするのは面倒くさいから、勝手にするようにしてくれないか?」というワガママなRLお客様のご注文の為に。。(笑
Windows Imaging Acquisitionを参照設定に追加してから、要するに基本は以下の通りでした。。
using WIA;
・
・
public partial class Form1 : Form
{
public Form1(string[] args)
{
InitializeComponent();
(以下、なんだか色々)
}
・
・
private void scan()
{
WIA.CommonDialog dlg = new WIA.CommonDialog();
ImageFile Image = dlg.ShowAcquireImage(WiaDeviceType.ScannerDeviceType,
WiaImageIntent.ColorIntent, WiaImageBias.MaximizeQuality,
"{B96B3CAE-0728-11D3-9D7B-0000F81EF32E}", true, true, true);
string p = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
System.IO.File.Delete(p + @"\tmp.bmp");
Image.SaveFile(p + @"\tmp.bmp");
}
}
ImageFile.SaveFile()メソッドは同名ファイルがあると例外をスローする様ですので、先に消しておくくらいでしょうか。。
LSLでところてんになった頭でたま~にWindowsアプリを作ろうとすると、ほんっとに今の環境はなんでも考えずに出来ますね。。メモリーは馬鹿みたいにありますしCPUは遊んでますし。。^^;
我ながら子供の遊びレベルです。。
2010年02月04日
lsl 乱数生成器
簡単な暗号通信をしたいと思い立ち、計算が軽い物を。。。
乱数に関しましては、北国ぺんぎん様のブログにもっと長周期(現在最強?)のものが紹介されております。
鍵になる文字列からハッシュを生成し、それを元にxorShift32乱数で4つのSeedを生成し、そのSeedを元にxorShift128乱数を生成します。
受信側と送信側のSeedが同期している限り復号し、同期が取れなくなると復号できなくなります。
乱数に関しましては、北国ぺんぎん様のブログにもっと長周期(現在最強?)のものが紹介されております。
鍵になる文字列からハッシュを生成し、それを元にxorShift32乱数で4つのSeedを生成し、そのSeedを元にxorShift128乱数を生成します。
受信側と送信側のSeedが同期している限り復号し、同期が取れなくなると復号できなくなります。
// www.lsleditor.org by Alphons van der Heijden (SL: Alphons Jano)
integer x = 123456789;
integer y = 362436069;
integer z = 521288629;
integer w = 88675123;
//***************************************************
//暗号化
//***************************************************
string alphabet="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/*-+.!\"#$%&'()~^|@{}[]*;?/_";
string encode(string txt)
{
integer n=llStringLength(txt);
string s="";
while(n--)
{
integer v=llRound(xorShift128(1.0)*(llStringLength(alphabet)-1));
s=llGetSubString(alphabet,v,v)+s;
}
return llXorBase64StringsCorrect(llStringToBase64(txt),llStringToBase64(s));
}
//***************************************************
//復号
//***************************************************
string decode(string crypt)
{
integer n=llStringLength(llBase64ToString(crypt));
string s="";
while(n--)
{
integer v=llRound(xorShift128(1.0)*(llStringLength(alphabet)-1));
s=llGetSubString(alphabet,v,v)+s;
}
return llBase64ToString(llXorBase64StringsCorrect(crypt,llStringToBase64(s)));
}
//論理右シフト
integer shrl(integer i,integer j)
{
return ((i >> j) & (0x7fffffff >> j-1));
}
//RSハッシュ
integer rsHash(string str)
{
integer len=llStringLength(str);
integer b = 378551;
integer a = 63689;
integer hash = 0;
while(str!="")
{
if (str!="")
{
while (llStringLength(str)<4)
{
str=str+" ";
}
}
string s1=llGetSubString(str,0,3);
str=llGetSubString(str,4,len);
integer i=llBase64ToInteger(llStringToBase64(s1));
integer k=llStringLength(s1);
while(k--)
{
hash = hash * a + (((i & (0x000000ff << 8*k)) >> 8*k) & 0x000000ff);
a = a * b;
}
}
return hash;
}
//Seed初期化(XorShift32)
randmize(string k)
{
integer y0=rsHash(k);
y0=y0^(y0<<13);
y0=y0^shrl(y0,17);
x=y0^(y0<<5);
y0 =y0^(y0<<13);
y0=y0^shrl(y0,17);
y=y0^(y0<<5);
y0=y0^(y0<<13);
y0= y0^shrl(y0,17);
z=y0^(y0<<5);
y0=y0^(y0<<13);
y0=y0^shrl(y0,17);
w=y0^(y0<<5);
}
//XorShift乱数(周期2^128-1)
float xorShift128(float f)
{
do
{
integer t = x ^ (x << 11);
x = y;
y = z;
z = w;
w =(w ^ shrl(w,19)) ^ (t ^ shrl(t,8));
} while(w==-2147483648);
return ((float)(2147483647-llAbs(w))/2147483646.0*f);
}
default
{
state_entry()
{
randmize("abdcefg");
}
touch_start(integer total_number)
{
integer a=x;
integer b=y;
integer c=z;
integer d=w;
string test="Rocket FM is great!";
llSay(0,test);
string crypt=encode(test);
llSay(0,llBase64ToString(crypt));
x=a;
y=b;
z=c;
w=d;
llSay(0,decode(crypt));
}
}
2009年08月31日
lslのlistで連想配列もどき・・
listがあまりにも不便なので、便利物です。
hash_add(string 名称 , list 値のリスト)
戻りはありません。名称を識別名にして、値のリストを登録します。
list hash(string 名称)
名称を登録済みの内容から検索して、見つかった値のリストを返します。
list hash_remove(string 名称)
名称を登録済みの内容から検索して、見つかった値のリストを返した上で、登録内容から削除します。
popの代用品の様な動き。
hash_clear()
登録内容を全消しします。
内容的には、与えられた名前,listの長さ,値のリスト・・・が順番に並んでいて、名前を探して見つかったものを出してくるだけの簡単なものです。
本当はなんと言う名前なんでしょう。。無学が曝されます。。
hash_add(string 名称 , list 値のリスト)
戻りはありません。名称を識別名にして、値のリストを登録します。
list hash(string 名称)
名称を登録済みの内容から検索して、見つかった値のリストを返します。
list hash_remove(string 名称)
名称を登録済みの内容から検索して、見つかった値のリストを返した上で、登録内容から削除します。
popの代用品の様な動き。
hash_clear()
登録内容を全消しします。
内容的には、与えられた名前,listの長さ,値のリスト・・・が順番に並んでいて、名前を探して見つかったものを出してくるだけの簡単なものです。
本当はなんと言う名前なんでしょう。。無学が曝されます。。
//ハッシュ?の登録
list tmpHash=[];
hash_add(string mykey,list l)
{
mykey="LSL_TMP_HASH"+mykey;
integer i=llListFindList(tmpHash,[mykey]);
if (i<0)
{
tmpHash+=[mykey,llGetListLength(l)]+l;
return;
}
else
{
integer len=llList2Integer(tmpHash,i+1);
tmpHash=llListReplaceList(tmpHash,[llGetListLength(l)]+l,i+1,i+len+1);
}
}
//ハッシュ?の削除
//削除されたリストを返す
list hash_remove(string mykey)
{
mykey="LSL_TMP_HASH"+mykey;
integer i=llListFindList(tmpHash,[mykey]);
if (i<0)
{
return [];
}
else
{
integer len=llList2Integer(tmpHash,i+1);
list l=llList2List(tmpHash,i+2,i+len+1);
tmpHash=llListReplaceList(tmpHash,[],i,i+len+1);
return l;
}
}
//ハッシュ?の読み出し
list hash(string mykey)
{
mykey="LSL_TMP_HASH"+mykey;
integer i=llListFindList(tmpHash,[mykey]);
if (i<0) return [];
integer len=llList2Integer(tmpHash,i+1);
return llList2List(tmpHash,i+2,i+len+1);
}
//ハッシュ?の全消し
hash_clear()
{
tmpHash=[];
}
2009年08月09日
PIの比較で90度と270度を切り分けるには・・
ループ処理で角度を加算している部分で、
単純に
if(Theta==PI*0.5) {} else if (Theta==PI*1.5) { }
では浮動小数点の比較でうまくいかない状態でした。
そこで、
if ((float)((string)(Theta*RAD_TO_DEG))==90.0) { }
の様に、いったん文字列にした後にfloatに戻して比較すると期待通りに動作しました。
また、PHPのround()関数の様な物を用意しておいて、任意ケタでいったん丸めてから比較してやると動きました。
型変換とどちらが良いのでしょうか。。。ちょっと不明。
もっとも、90度と270度を切り分けるなんて、めったに出てきませんが・・^^;
単純に
if(Theta==PI*0.5) {} else if (Theta==PI*1.5) { }
では浮動小数点の比較でうまくいかない状態でした。
そこで、
if ((float)((string)(Theta*RAD_TO_DEG))==90.0) { }
の様に、いったん文字列にした後にfloatに戻して比較すると期待通りに動作しました。
また、PHPのround()関数の様な物を用意しておいて、任意ケタでいったん丸めてから比較してやると動きました。
型変換とどちらが良いのでしょうか。。。ちょっと不明。
もっとも、90度と270度を切り分けるなんて、めったに出てきませんが・・^^;
// www.lsleditor.org by Alphons van der Heijden (SL: Alphons Jano)
float round(float a,integer p)
{
float t=llPow(10.0,p);
return llRound(a*t)/t;
}
test(float theta)
{
if (ceil(theta,6)==ceil(0.5*PI,6)) {
llSay(0, "0.5");
}else if (ceil(theta,6)==ceil(1.5*PI,6))
{
llSay(0, "1.5");
}
}
default
{
state_entry()
{
integer i=64;
float dtheta=2.0*PI/i;
float theta=0;
while(i--)
{
theta=dtheta*i;
test(theta);
}
}
}
2009年08月08日
LSLコード色づけ~これはすごいですね
Hidenori Glushenko様作成によるスクリプト整形CGI
これは便利です。(;_;/~
色づけはもちろん、Wikiへのリンクも自動的に行ってくれます。
詳細はScripters Cafe・「ブログ用LSLコード色づけ」で解説しておられます。
これは便利です。(;_;/~
色づけはもちろん、Wikiへのリンクも自動的に行ってくれます。
詳細はScripters Cafe・「ブログ用LSLコード色づけ」で解説しておられます。
2009年08月02日
パーティクル設定項目について
パーティクルの設定項目で特にわかりにくかったものを、忘れないためにメモ。
PSYS_SRC_PATTERN_ANGLE
PSYS_SRC_ANGLE_BEGINとPSYS_SRC_ANGLE_ENDで指定された平坦な扇形(V字?)にパーティクルを噴霧。
この際、放出平面はYZ平面上となり、PSYS_SRC_ANGLE_BEGIN、PSYS_SRC_ANGLE_ENDはいずれもZ軸が0度となる角度(ラジアン)。

PSYS_SRC_PATTERN_ANGLE_CONE
PSYS_SRC_ANGLE_BEGINとPSYS_SRC_ANGLE_ENDで指定されたコーン(円錐?)にパーティクルを噴霧。
PSYS_SRC_ANGLE_BEGIN、PSYS_SRC_ANGLE_ENDはいずれもZ軸が0度となる角度(ラジアン)。
PSYS_SRC_BURST_RADIUS
噴霧が開始される位置の中心からの距離(半径・メートル)。
ただし、オブジェクトと共に移動するマスク(PSYS_PART_FOLLOW_SRC_MASK)が指定されている場合は無視されてしまうので注意。
PSYS_PART_FOLLOW_VELOCITY_MASK
指定するとパーティクルの上端が常に進行方向を向くようになります。
なので、上向きの矢印などをテクスチャに指定しておくと、弓矢が飛んでいく様な見え方。
PSYS_SRC_PATTERN_ANGLE
PSYS_SRC_ANGLE_BEGINとPSYS_SRC_ANGLE_ENDで指定された平坦な扇形(V字?)にパーティクルを噴霧。
この際、放出平面はYZ平面上となり、PSYS_SRC_ANGLE_BEGIN、PSYS_SRC_ANGLE_ENDはいずれもZ軸が0度となる角度(ラジアン)。

PSYS_SRC_PATTERN_ANGLE_CONE
PSYS_SRC_ANGLE_BEGINとPSYS_SRC_ANGLE_ENDで指定されたコーン(円錐?)にパーティクルを噴霧。
PSYS_SRC_ANGLE_BEGIN、PSYS_SRC_ANGLE_ENDはいずれもZ軸が0度となる角度(ラジアン)。
PSYS_SRC_BURST_RADIUS
噴霧が開始される位置の中心からの距離(半径・メートル)。
ただし、オブジェクトと共に移動するマスク(PSYS_PART_FOLLOW_SRC_MASK)が指定されている場合は無視されてしまうので注意。
PSYS_PART_FOLLOW_VELOCITY_MASK
指定するとパーティクルの上端が常に進行方向を向くようになります。
なので、上向きの矢印などをテクスチャに指定しておくと、弓矢が飛んでいく様な見え方。