2009年08月08日
LSLコード色づけ~これはすごいですね
Hidenori Glushenko様作成によるスクリプト整形CGI
これは便利です。(;_;/~
色づけはもちろん、Wikiへのリンクも自動的に行ってくれます。
詳細はScripters Cafe・「ブログ用LSLコード色づけ」で解説しておられます。
これは便利です。(;_;/~
色づけはもちろん、Wikiへのリンクも自動的に行ってくれます。
詳細はScripters Cafe・「ブログ用LSLコード色づけ」で解説しておられます。
2009年08月08日
スカート製造装置(物体の回転その3)

楕円の方程式は
x*x/a*a-y*y/b*b=1
y=tan(θ)*x
を代入して変形すると、
(1/a/a+tan(θ)*tan(θ)/b/b)x*x-1=0
となり、あとは二次方程式の根の公式なり、手計算変形なりで部品をrezすべきy座標はみつかります。
それに対空砲を組み合わせてやれば、スカートは自動で製造出来るということになります。
多少アレンジして設定ファイルを読み込むようにしました。
本体が入っているオブジェクトの中にsettingsがあり、本体のインベントリにスカートの部品をいれると準備が完了します。あとはタッチで。
本体
//90度を何分割するか
integer maxNumOfPartitions=10;
//楕円のX軸方向の半径(メートル)
float a=0.25;
//楕円のY軸方向の半径(メートル)
float b=0.2;
//ひらひらの縦方向の傾き(度)。プラス指定で上がすぼまる
float ThetaZ=10;
//スカートを出現させる位置の装置中心からのX軸距離
float offsetX=0.0;
//スカートを出現させる位置の装置中心からのY軸距離
float offsetY=0.0;
//スカートを出現させる装置中心位置からの高さ調整
float offsetZ=0.5;
//X平面から離れていく大きさ
float dXZ=0;
//X平面から離れていく大きさ
float dYZ=0;
float x1=0.0;
float y1=0.0;
float dTheta=PI;
float Theta=0;
string partsName="";
key settingsHandle;
integer settingsLine;
list objectNames_Inventory=[];
integer isReading=FALSE;
integer isMaking=FALSE;
init()
{
Theta=0;
//設定読み込み
readConf();
//向き直る
llSetRot(ZERO_ROTATION);
}
readConf()
{
//設定のノートカード読み取り
isReading=TRUE;
settingsLine=0;
settingsHandle=llGetNotecardLine("settings",settingsLine);
}
remveObject()
{
//インベントリー内部掃除
integer num=llGetInventoryNumber(INVENTORY_OBJECT);
integer i=0;
if (num!=INVENTORY_NONE)
{
for (i=0;i<num;i++)
{
llRemoveInventory(llGetInventoryName(INVENTORY_OBJECT,0));
}
}
}
setPoint()
{
if (llFabs(Theta)==PI/2)
{
y1=b;
}
else
{
y1=llSqrt((1-x1*x1/a/a)*b*b);
}
}
rezOb(float x,float y)
{
vector targetVec=<x,y,0>;
vector norm=llVecNorm(targetVec);
rotation newRot=llRotBetween(<1,0,0>,<norm.x,norm.y,0>);
rotation newRot2=llEuler2Rot(<0,PI+ThetaZ*DEG_TO_RAD*-1.0,0>);
if (partsName!="" && llGetInventoryKey(partsName)!=NULL_KEY)
{
llRezObject(partsName,llGetRootPosition()+<x+offsetX,y+offsetY,offsetZ*-1-x*llSin(dXZ*DEG_TO_RAD)-y*llSin(dYZ*DEG_TO_RAD)>,ZERO_VECTOR,newRot2*newRot,1);
}
}
rezObject()
{
setPoint();
rezOb(x1,y1);
rezOb(x1*-1,y1);
rezOb(x1,y1*-1);
rezOb(x1*-1,y1*-1);
}
default
{
state_entry()
{
init();
remveObject();
}
on_rez(integer start_param)
{
init();
remveObject();
}
touch_start(integer total_number)
{
if (isMaking)
{
llSay(0,"Ooops! Now,I'm busy.Please wait a moment");
return;
}
llSay(0,"Start create a new skirt");
if (partsName=="" || llGetInventoryKey(partsName)==NULL_KEY)
{
llOwnerSay("ERROR:I can't find prim "+partsName+" in my inventory.");
return;
}
isMaking=TRUE;
init();
llSetTimerEvent(0.1);
}
timer()
{
if (isReading)
{
return;
}
llSetTimerEvent(0.0);
integer i=0;
float CA=0;
float CB=0;
float CC=-1;
rezOb(a,0);
rezOb(a*-1,0);
rezOb(0,b);
rezOb(0,b*-1);
for (i=1;i<maxNumOfPartitions;i++)
{
Theta=dTheta*i;
CA=1/a/a+llTan(Theta)*llTan(Theta)/b/b;
x1=(llSqrt(CB*CB-4*CA*CC)-CB)/(2*CA);
rezObject();
}
llSleep(2.0);
llSay(0,"Finished");
isMaking=FALSE;
}
changed(integer change)
{
integer num=llGetListLength(objectNames_Inventory);
integer num2=llGetInventoryNumber(INVENTORY_OBJECT);
integer i=0;
string objName="";
integer j=-1;
list tmp=[];
if (change & CHANGED_INVENTORY)
{
if (num2>0)
{
for (i=0;i<num2;i++)
{
objName=llGetInventoryName(INVENTORY_OBJECT,i);
tmp+=objName;
j=llListFindList(objectNames_Inventory,[objName]);
if (j==-1)
{
partsName=objName;
llOwnerSay("Found new item:"+partsName);
}
}
}
else
{
partsName="";
}
objectNames_Inventory=tmp;
}
}
dataserver(key requested, string data)
{
integer p=-1;
string m1="";
string com="";
if (requested==settingsHandle)
{
if (data != EOF) {
p=llSubStringIndex(data,"//");
if (p==-1)
{
//データー行
p=llSubStringIndex(data,":");
m1=llGetSubString(data,p+1,llStringLength(data)-1);
com=llGetSubString(data,0,p-1);
if (com=="Partitions") maxNumOfPartitions=(integer)m1;
if (com=="Ra") a=(float)m1;
if (com=="Rb") b=(float)m1;
if (com=="AngleZ") ThetaZ=(float)m1;
if (com=="PositionX") offsetX=(float)m1;
if (com=="PositionY") offsetY=(float)m1;
if (com=="PositionZ") offsetZ=(float)m1;
if (com=="deltaXZ") dXZ=(float)m1;
if (com=="deltaYZ") dYZ=(float)m1;
}
settingsLine++;
settingsHandle=llGetNotecardLine("settings",settingsLine);
}
else
{
//dθ
dTheta=PI/2/maxNumOfPartitions;
//初期位置
x1=a;
isReading=FALSE;
}
}
}
}
設定ファイル(ノートカード:settings)
//90度を何分割するか(正の整数)
Partitions:2
//楕円のX軸方向の半径(正の実数・メートル)
Ra:0.25
//楕円のY軸方向の半径(正の実数・メートル)
Rb:0.2
//ひらひらの縦方向すぼまりの傾き(正の実数・度)。
//プラス指定で上がすぼまるテーパー状に配置されます。
AngleZ:20
//スカートを出現させる装置中心位置からのX位置調整(実数・メートル)
//0でマネキンの位置。
PositionX:0
//スカートを出現させる装置中心位置からのY位置調整(実数・メートル)
//0でマネキンの位置。
PositionY:0
//スカートを出現させる装置中心位置からの高さ調整(実数・メートル)
//値を大きくすると下に下がります。
//パーツのZ軸サイズの半分で大体マネキンの腰のあたりになります。
PositionZ:0.25
//X軸とスカート上端面の傾き(実数・度)
//指定が0以外の場合、前方向から見て傾斜して見えます。
deltaXZ:0
//Y軸とスカート上端面の傾き(実数・度)
//指定が0以外の場合、横方向から見て傾斜して見えます。
deltaYZ:10