QRコード
QRCODE
アクセスカウンタ
読者登録
メールアドレスを入力して登録する事で、このブログの新着エントリーをメールでお届けいたします。解除は→こちら
現在の読者数 0人
オーナーへメッセージ
slMame › 一日一膳腹八分目

  

Posted by at
2023年12月18日

LSLエディタ勝手に改造版⑦



http://www.tam.ne.jp/rbk/lslEditor/LSLEditor.exe
(↓落とせない場合はコチラ。中身は一緒です)
http://www.tam.ne.jp/rbk/lslEditor/LSLEditor.zip

ウィルスチェックは自己責任でお願いいたします。チェックしておりません。
実行や解凍が出来ない場合はファイルのプロパティを開き、「セキュリティ」の右にある「許可する」にチェックを入れてください。

インストーラーではなく、そのまま実行ファイルですので、既存のフォルダ内の同じファイルを上書きしてください。既存ファイルが無くても問題なく動作します。
バージョン数字勝手に修正しています。(本家更新がかかった場合にバージョン番号が変わりますので、自動アップデート機能は一応ONのままを推奨いたします。どうにも望み薄の気配ですが・・)
デバッグ機能(F5キー)は意味がないのと対応させていませんのでキーショートカットもメニューも殺してあります。構文チェック(F6キー)は実装させています。

今回より、ターゲットフレームワークを.Net2.0から.Net4.8に変更しています。動かない場合は.Netフレームワーク4.8以降をインストールしてみてください。



本家公開版はこちら。(無くなってしまっていたのでリンクを外しました)
ttp://www.lsleditor.org/

ソース取得元はこちら。
http://sourceforge.net/projects/lsleditor/files/Source/


LSLEditorはGPL2ライセンスです。
改変後ソースが何が何でも必要な方はIM等でご一報ください。いらないと思いますが。。w
  


Posted by RBK Drachnyd(しお) at 00:32Comments(0)
2017年02月06日

スーパーリアル8ビット3D’SK’





発売開始です。
このカクカクの代物に3か月の時間とパワーを費やすとは正直予想していませんでした。。MPがもうありません。ムフー
↓動画の通りの飛び方をします。既存のSL飛行機の常識は通用しません。というか壊す気満々です。(-_-+



実売地はこちら


基本的な販売形態はガチャですので、デモRezzerはございません。
エンジンパワーの強弱がある以外は戦闘機はほぼ同一です。(但しそのパワーが不足気味の機体は離陸注意!なのは相変わらずですが。。w)
グリーンは特に気を付けてください。不用意に機首上げするとあっという間に落っこちます。

爆撃機の飛行特性はまるで別物です。機首上げ機首下げを繰り返すピッチング運動をしますので安定しなくても慌てずゆっくり操作してください。
赤とんぼ(Dragonfly)だけは二人乗りできます。
  


Posted by RBK Drachnyd(しお) at 00:04Comments(0)作成物/製品
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);

と二発重ねて使う事が多いだろうと思いますが、これもかなり強力な機能強化だと思います。  


Posted by RBK Drachnyd(しお) at 05:52Comments(0)忘れない為に。。
2016年09月11日

LSLエディター勝手に改造版⑥



http://www.tam.ne.jp/rbk/lslEditor/LSLEditor.exe
(↓落とせない場合はコチラ。中身は一緒です)
http://www.tam.ne.jp/rbk/lslEditor/LSLEditor.zip

ウィルスチェックは自己責任でお願いいたします。チェックしておりません。
圧縮ファイルやインストーラーではなく、そのまま実行ファイルですので、既存のフォルダ内の同じファイルを上書きしてください。
バージョン数字勝手に修正しています。(本家更新がかかった場合にバージョン番号が変わりますので、自動アップデート機能は一応ONのままを推奨いたします。どうにも望み薄の気配ですが・・)
デバッグ機能(F5キー)は意味がないのと対応させていませんのでキーショートカットもメニューも殺してあります。構文チェック(F6キー)は実装させています。

llGetObjectDetails()の取得可能定数項が増えていたのは嬉しい機能強化ですね。


以下の関数類で「new」や「I」が表示されているもので足りない物を追加しました。
http://wiki.secondlife.com/wiki/Category:LSL_Functions

llGetObjectDetails()でこっそり追加されていた定数類を追加しました。OPT_*系の定数類も追加ししました。

LlGetExperienceErrorMessage()で使われるXP_*系定数を追加しました。




本家公開版はこちら。(無くなってしまっていたのでリンクを外しました)
ttp://www.lsleditor.org/

ソース取得元はこちら。
http://sourceforge.net/projects/lsleditor/files/Source/


LSLEditorはGPL2ライセンスです。
改変後ソースが何が何でも必要な方はIM等でご一報ください。いらないと思いますが。。w
  


Posted by RBK Drachnyd(しお) at 14:16Comments(0)雑記
2016年04月15日

飛行機をつくる:(3) 乗り物パラメーターをいじる

3回目では前回までのなんちゃって飛行機の中の、乗り物システムをもう少し自分なりに好きなようにいじれるように、乗り物システムの設定を詳しく見ていく事にします。

前回までのなんちゃって飛行機では、乗り物システムに対する命令は関数planeEngine()のなかで下の様になっていました。
//-----------------------------------------
//エンジン設定関数 planeEngine()
//-----------------------------------------
planeEngine()
{
llSetVehicleType(VEHICLE_TYPE_AIRPLANE); //乗り物タイプを飛行機にします。
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE,0.0); //舵操作への反応速度を最高感度にします。
}

この中に出てくるllSetVehicleType()は、乗り物システムに乗り物のタイプを指定する命令ですが、動作としてはVEHICLE_TYPE_NONEを指定すると乗り物システムをオフにしてただのプリムにし、その他を選んだ際は(リンデンの中の人が思う所の)名前の通りの乗り物の様な動きをする初期設定を一発設定する、という関数です。
ですので、実際には乗り物タイプの指定というよりも、乗り物システムをオンオフする関数、という方が正確です。
車や船やバルーンや飛行機と、色々なタイプ指定がありますが、どれを選んでも指定される値が異なるだけで、指定するパラメーターの種類は同一で、乗り物システムに与えることが出来るほぼ全てのパラメーターに対して初期値を設定しに行くようになっています。
つまり、例えば車を作ろうとしている時に船を選んでも、パラメーターを全部上書きするなら普通に車になります。
例えば飛行機(VEHICLE_TYPE_AIRPLANE)であればこのようになっています。

// 前後方向には抵抗はとても小さい
llSetVehicleVectorParam( VEHICLE_LINEAR_FRICTION_TIMESCALE, <200, 10, 5> );
// 回転抵抗はどの方向も同じ
llSetVehicleFloatParam( VEHICLE_ANGULAR_FRICTION_TIMESCALE, 20 );
// 推進モーター
llSetVehicleVectorParam( VEHICLE_LINEAR_MOTOR_DIRECTION, <0, 0, 0> );
llSetVehicleFloatParam( VEHICLE_LINEAR_MOTOR_TIMESCALE, 2 );
llSetVehicleFloatParam( VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 60 );
// 回転モーター
llSetVehicleVectorParam( VEHICLE_ANGULAR_MOTOR_DIRECTION, <0, 0, 0> );
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE, 4 );
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 8 );
// ホバーさせない
llSetVehicleFloatParam( VEHICLE_HOVER_HEIGHT, 0 );
llSetVehicleFloatParam( VEHICLE_HOVER_EFFICIENCY, 0.5 );
llSetVehicleFloatParam( VEHICLE_HOVER_TIMESCALE, 1000 );
llSetVehicleFloatParam( VEHICLE_BUOYANCY, 0 );
// 線形偏向
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.5 );
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.5 );
// 角度偏向
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 1.0 );
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 2.0 );
// 垂直アトラクター
llSetVehicleFloatParam( VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.9 );
llSetVehicleFloatParam( VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 2 );
// バンク効果
llSetVehicleFloatParam( VEHICLE_BANKING_EFFICIENCY, 1 );
llSetVehicleFloatParam( VEHICLE_BANKING_MIX, 0.7 );
llSetVehicleFloatParam( VEHICLE_BANKING_TIMESCALE, 2 );
// 乗り物モーターの取り付け角度
llSetVehicleRotationParam( VEHICLE_REFERENCE_FRAME, <0, 0, 0, 1> );
// これらのフラグをオフにします
llRemoveVehicleFlags( VEHICLE_FLAG_NO_DEFLECTION_UP
| VEHICLE_FLAG_HOVER_WATER_ONLY
| VEHICLE_FLAG_HOVER_TERRAIN_ONLY
| VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT
| VEHICLE_FLAG_HOVER_UP_ONLY
| VEHICLE_FLAG_LIMIT_MOTOR_UP );
// これらのフラグをオンにします
llSetVehicleFlags( VEHICLE_FLAG_LIMIT_ROLL_ONLY );

結局、上の枠内の設定を色々といじり倒して、望むような動き方をする設定パラメーターを見つければ、望むような乗り物が作れる(大抵は!)という事です。以下、順序が多少変わるかもしれませんが一つづつ見ていきます。

VEHICLE_LINEAR_FRICTION_TIMESCALE

X,Y,Zの各々の方向に対する速度の減衰程度を、3軸とも同じならfloatで、各軸について変えたいならvectorで指定します。
停止するまでの時間スケールを表しているので、値が大きくなるほど抵抗が減ります。
但し、下の方で説明する他のいくつかのパラメーターの方が効果が圧倒的に強いので、抵抗を小さくしようとして値を大きくしてもあまり効き目が感じられません。抵抗を大きくするために設定値を小さくするとそれなりに効きます。


VEHICLE_ANGULAR_FRICTION_TIMESCALE

X,Y,Zの各々の方向に対する回転の減衰程度を、3軸とも同じならfloatで、各軸について変えたいならvectorで指定します。
停止するまでの時間スケールを表しているので、値が大きくなるほど抵抗が減ります。
但し、こちらもいくつかのパラメーターの方が効果が圧倒的に強い事が多いので、おまけ程度の意味と思っておく方がよいかもしれません。


推進モーター系3種

VEHICLE_LINEAR_MOTOR_DIRECTION
推進モーター(線形モーター)つまり、XYZ各方向に進もうとさせるスピードをvectorで指定します。指定した速度で進もうとします。
VEHICLE_LINEAR_MOTOR_TIMESCALE
推進モーターの出力が最大に到達するまでの時間スケールを指定します。大きくすると加速が遅くなります。
VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE
推進モーターの出力が最大に達した後、減衰して無くなってしまうまでの時間スケールを指定します。大きくすると最大速度付近で延々と移動し続けようとします。但し最大で2分ほどでだんだん減衰が始まり、そのうち停止します。

これら推進モーター系3種類のパラメーターで、乗り物のスロットル(アクセル)を入れたときのスピードやスピードアップの速さを調整するのですが、飛行機にとっては多少微妙な動きをします。
例えば、<5, 0, 0>を設定したとすると飛行機は前方向に5メートル毎秒の速さで移動しようとし始めるのですが、このとき、ゼロを指定しているYとZについても、何もしないのではなくて速度ゼロになろうとする様に振舞います。この振る舞いによる減速はVEHICLE_LINEAR_MOTOR_TIMESCALEで指定した推進エンジンの追随時間に応じて発揮されるので、(すみやかに加速したい≒大抵の場合)3軸毎の抵抗の設定よりも大きな抵抗が発生している様に感じられます。
車でもドリフト動作等のちょっと変わった動きをさせたい時に邪魔をしている可能性がありますが、飛行機における影響はかなり深刻で、<1, 0, 0>を設定したとすると飛行機は前方向に1メートル毎秒の速さで移動しようとしつつ、Z軸の指定がゼロなので無重力でその高さに留まろうとします
UFOといわれる空中で停止しながらクルクル回る物体の正体は要するにこれです。。^^;


回転モーター系3種

VEHICLE_ANGULAR_MOTOR_DIRECTION
回転モーター(舵機能)に、XYZの各軸廻りでの回転動作をラジアン毎秒で指定します。指定の回転速度で回転しようとしますが、いくつか他のパラメーターに影響を受けるものがあります。
VEHICLE_ANGULAR_MOTOR_TIMESCALE
回転モーターに指定した回転速度に到達するまでの時間スケールを指定します。値を大きくすると回転がゆっくりスタートします。
VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE
回転モーターに指定した回転力が最大に達したのちに、減衰して無くなってしまうまでの時間スケールを指定します。値を大きくするといつまでも回り続けようとしますが、値に関わらずそのうち停止します。

回転モーター系は推進モーターと違い、他のパラメーターに悪さをする要素は余りなく、素直に書いてある通りに使えます。
ゼロ指定をすると回転を停止させようとするのは推進モーターと同じですが、大抵の乗り物は回転は速やかにやめたい物なので、こちらはあまり気になりません。
回転力そのものは下で説明する偏向・アトラクターによって影響を受け、大抵の場合指定より小さな効果しか及ぼさなくなります。
例えば、偏向やアトラクターを調整していると突然ちっとも曲がらなくなった!という風になります。壊れた!と慌てない様に注意です。


線形偏向

VEHICLE_LINEAR_DEFLECTION_EFFICIENCY
乗り物の正面が向いている方向に移動する方向を変えようとする性質の強さです。
0.0(効果なし)から1.0(最大)の間で指定します。
VEHICLE_LINEAR_DEFLECTION_TIMESCALE
線形偏向の強さが最大に発揮されるまでの時間スケールを指定します。値を大きくすると効果の発揮がゆっくりになります。

線形偏向は飛行機にとって非常にクセモノです。恐らく車のドリフトや、車がバウンドして浮いてしまった後の落下速度にも悪影響を与えます。
乗り物の正面方向に速度を向けたがる性質という事ですので、リンデンの説明を一見するととっても有意義な設定パラメーターに見えるのですが、、、

例えば空中で推進力をゼロにした上で真上を向くと・・

1)重力によって速度が落ちていき・・・
2)空中で停止し・・・
3)重力によって落下しはじめて・・・
4)線形偏向が落下を前進力に変換し・・・
5)振り出しに戻る

というループが発生して、結果、空中でほぼ静止する画期的なUFOが出来上がります(笑
また、回転モーターへの設定値が小さい状態でこの線形偏向パラメーターが大きいと、まったく曲がらなくなります。
普通の挙動であれば推進モーターへの出力ゼロ指定で横や縦へのすべりはある程度止められるので、ご利用は計画的にといった感想を私は抱いています。


角度偏向

VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY
現在乗り物が進んでいる方向に正面を向けようとする傾向の強さを0.0(傾向無し)~1.0(最大)の間で指定します。
VEHICLE_ANGULAR_DEFLECTION_TIMESCALE
角度偏向の強さが最大に発揮されるまでの時間スケールを指定します。

角度偏向は線形偏向ほどには悪さをしない傾向パラメーターで、飛行機で言えば水平尾翼と垂直尾翼の効果に該当する傾向を表します。つまり、機体が今進んでいる方向にむこうとします。
線形偏向が大きいと殆ど効果を表しませんが、旋回操作をやめると元の方向にボヨヨンと戻ろうとする傾向の強さになって現れます。
進んでいた方向に戻ろうとする成分なので回転モーターと逆向きの力が加わる事が多く、その意味で若干の影響を回転に与えます。


垂直アトラクター

VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY
傾斜した姿勢を立て直そうとする傾向の強さを0.0(効果無し)~1.0(最大)の範囲で指定します。
VEHICLE_VERTICAL_ATTRACTION_TIMESCALE
姿勢復元傾向が最大に発揮するまでの時間スケールを指定します。値が大きくなるほどゆっくり・弱くなります。

後述するフラグVEHICLE_FLAG_LIMIT_ROLL_ONLYによって影響を受けますが、傾斜した姿勢にある状態を自動的にまっすぐに立て直そうとする傾向を指定するパラメーターの組です。
飛行機で言えば、傾斜して旋回していた機体が放置しておくと段々傾斜が復元され、水平に戻っていく効果の大きさに該当します。メインランドを観光飛行する様な用途では大きめの値の方がクルーズしやすくなりますが、あまり傾向が強いと曲がるのにキー連打が必要になったりして旋回操作が忙しくなります。


バンク効果

VEHICLE_BANKING_MIX
機体を傾斜させたときに発生する旋回力の出方を0.0(停止していても曲がる)~1.0(動いていないと曲がらない)の間で設定します。
VEHICLE_BANKING_EFFICIENCY
乗り物が傾斜した時に曲がろうとする方向を-1.0(逆方向に曲がる)~0.0(効果なし)~1.0(傾いた方向に曲がる)の範囲で設定します。
VEHICLE_BANKING_TIMESCALE
傾斜によって旋回が発生するまでの時間スケールを設定します。

飛行機では、機体をバンクさせたときにその方向に曲がりはじめる傾向に該当する効果を生み出します。
船などでバンクさせた方向と逆方向に曲がるように設定するのも面白いかもしれません。
メインランド飛行用の機体などではこれと垂直アトラクター(傾斜からの復元傾向)を上手く調整して、45度傾斜ぐらいからスタートで~100メートル程度の半径で曲がり終わり、曲がり終わると傾斜が復元してまっすぐ飛ぶようになっていると割と乗りやすい機体になると思います。(その程度にしておくと1SIMの中で90度曲がって姿勢が復元し、そのまま次のSIMに侵入します)


ホバー

VEHICLE_HOVER_HEIGHT
乗り物が空中や水中を浮遊する高さの目標値をメートルで指定します。ゼロメートルの基準になる高さは後述のフラグで指定します。
VEHICLE_HOVER_EFFICIENCY
ホバー高度に到達しようとする傾向を0.0(ピーキー)~1.0(鈍い)の範囲で指定します。
VEHICLE_HOVER_TIMESCALE
ホバーの目標高度に到達するまでの目標時間スケールを指定します。値が大きいほどゆっくりになります。
VEHICLE_BUOYANCY
乗り物にかかる重力の大きさを、-1.0(2G)~0(1G)~1.0(無重力)の範囲で指定します。重力加速度は高校物理の通り1Gが9.8メートル毎秒毎秒になっていますので、働いている力の大きさはここで指定した重力加速度にllGetMass()をかけた物になります。また、llSetBuoyancy()で指定する重力の大きさとは独立して働いています。

後述するフラグによって定めたゼロメートル地点(地上、水面、絶対)から見て、乗り物が指定の高度で浮遊する傾向を設定するパラメーターの組です。普通の飛行機では関係が無いのでリンデンの初期設定のままでもかまいませんが、ハリアーやF35を作りたい人には関係のある設定です。
水上飛行機の場合は目標高度ゼロ付近、ゼロメートルは水面にして、水面では船と同じになるようにします。


フラグ設定

VEHICLE_FLAG_NO_DEFLECTION_UP
線形偏向(速度を正面に向けようとする傾向)が方向を変えようとする成分のうち、垂直方向の成分を対象にするかをオンオフします。
元々は車などが浮き上がらずに地面を這うようにするためのフラグらしいですが、バウンドが激しいと華麗に離陸します。
VEHICLE_FLAG_LIMIT_ROLL_ONLY
垂直アトラクター(傾斜姿勢の復元傾向)の対象成分をロール(左右傾斜)のみにするかをオンオフします。
飛行機は一般的にこのフラグをオンにしてロールだけを復元対象にしますが、実物の飛行機では実は上下方向の姿勢傾斜にも復元傾向が存在します。なお、フラグをオンにしてロールだけを復元対象にしていても、上下方向の回転への影響が若干残る様です。
VEHICLE_FLAG_HOVER_WATER_ONLY
ホバー高度のゼロメートル基準点を水面にするかをオンオフします。
VEHICLE_FLAG_HOVER_TERRAIN_ONLY
ホバー高度のゼロメートル基準点を地面にするかをオンオフします。
VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT
ホバー高度のゼロメートル基準点を絶対座標にするかをオンオフします。
VEHICLE_FLAG_HOVER_UP_ONLY
バグによってフラグの名前とは逆の効果を発揮します。オンにすると指定されているホバー高度よりも上に浮いている間はホバー機能が無効になります。
VEHICLE_FLAG_LIMIT_MOTOR_UP
オンにすると乗り物が地面から浮き上がろうとする効果を抑制するとの事ですが、車でオンにしても普通に離陸します。
VEHICLE_FLAG_MOUSELOOK_BANK
オンにするとマウスルックのカメラ方向で左右の姿勢傾斜が発生します。(エルロン類似)
VEHICLE_FLAG_MOUSELOOK_STEER
オンにするとマウスルックのカメラ方向で左右の首ふりが発生します。(ラダー類似)
VEHICLE_FLAG_CAMERA_DECOUPLED
オンにするとマウスルック時のカメラ方向が乗り物の向きと一致しなくなるとの事ですが・・・効果がよくわかりません。
お友達のかんなさんの情報によると上二つのマウスルックによる操作に影響を与えるとの事です。。


乗り物モーターの姿勢系

VEHICLE_REFERENCE_FRAME
線形モーター(推進エンジン)の取付け回転角をルートから見た相対回転のrotationで指定します。例えば造形の都合上で90度回転しているのが正常な乗り物に、それと逆回転を指定してやると期待通りの方向が正面方向になります。
VEHICLE_LINEAR_MOTOR_OFFSET
線形モーター(推進エンジン)の取付け位置が、乗り物の重心からずれている距離をvectorで指定します。
重心と推進エンジンがずれていると回転力になって現れますので通常は<0,0,0>のデフォルトのままでよいですが、飛行中に突然ずらすと錐もみや失速の様な急激で不思議な運動が発生するので狙って使ってみるのも面白い手だと思います。


ということで、前回のカメラ付スクリに上のデフォルトの飛行機パラメーター+回転速度だけは即座に反映、と変えて、今回の完成状態は以下の枠内になりました。
関数planeEngine()の中が増えて、全てのパラメーターを自分で調整できるようになっています。

key pilot=NULL_KEY; //パイロットのUUID
float throttle=0.0; //スロットル状態
vector angular_motor=ZERO_VECTOR; //舵操作状態
integer handle=0; //チャット傍受識別番号
integer camon=FALSE; //カメラタイプ
//-----------------------------------------
//初期化関数 init()
//-----------------------------------------
init()
{
llListenRemove(handle); //チャット傍受を解除します。
pilot=NULL_KEY; //pilotを初期化します。
llSetStatus(STATUS_PHYSICS,FALSE); //物理を切ってその場に停止させます。
camon=FALSE; //カメラタイプを初期化します。
}
//-----------------------------------------
//エンジン設定関数 planeEngine()
//-----------------------------------------
planeEngine()
{
llSetVehicleType(VEHICLE_TYPE_AIRPLANE); //乗り物タイプを飛行機にします。
// 前後方向には抵抗はとても小さい
llSetVehicleVectorParam( VEHICLE_LINEAR_FRICTION_TIMESCALE, <200, 10, 5> );
// 回転抵抗はどの方向も同じ
llSetVehicleVectorParam( VEHICLE_ANGULAR_FRICTION_TIMESCALE, <20,20,20> );
// 推進モーター
llSetVehicleVectorParam( VEHICLE_LINEAR_MOTOR_DIRECTION, <0, 0, 0> );
llSetVehicleFloatParam( VEHICLE_LINEAR_MOTOR_TIMESCALE, 2 );
llSetVehicleFloatParam( VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 60 );
// 回転モーター
llSetVehicleVectorParam( VEHICLE_ANGULAR_MOTOR_DIRECTION, <0, 0, 0> );
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE,0.0); //舵操作への反応速度を最高感度にします。
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 8 );
// ホバーさせない
llSetVehicleFloatParam( VEHICLE_HOVER_HEIGHT, 0 );
llSetVehicleFloatParam( VEHICLE_HOVER_EFFICIENCY, 0.5 );
llSetVehicleFloatParam( VEHICLE_HOVER_TIMESCALE, 1000 );
llSetVehicleFloatParam( VEHICLE_BUOYANCY, 0 );
// 線形偏向
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.5 );
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 0.5 );
// 角度偏向
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 1.0 );
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 2.0 );
// 垂直アトラクター
llSetVehicleFloatParam( VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 0.9 );
llSetVehicleFloatParam( VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 2 );
// バンク効果
llSetVehicleFloatParam( VEHICLE_BANKING_EFFICIENCY, 1 );
llSetVehicleFloatParam( VEHICLE_BANKING_MIX, 0.7 );
llSetVehicleFloatParam( VEHICLE_BANKING_TIMESCALE, 2 );
// 乗り物モーターの取り付け角度
llSetVehicleRotationParam( VEHICLE_REFERENCE_FRAME, <0, 0, 0, 1> );
//乗り物モーターの重心からのずれ
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_OFFSET,<0,0,0>);
// これらのフラグをオフにします
llRemoveVehicleFlags( VEHICLE_FLAG_NO_DEFLECTION_UP
| VEHICLE_FLAG_HOVER_WATER_ONLY
| VEHICLE_FLAG_HOVER_TERRAIN_ONLY
| VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT
| VEHICLE_FLAG_HOVER_UP_ONLY
| VEHICLE_FLAG_LIMIT_MOTOR_UP );
// これらのフラグをオンにします
llSetVehicleFlags( VEHICLE_FLAG_LIMIT_ROLL_ONLY );
}
//-----------------------------------------
//動的カメラ設定関数 setCamera()
//-----------------------------------------
setCamera()
{
if (camon)
{
//camonがTRUE⇒カメラコントロールあり
if ((llGetPermissions() & PERMISSION_CONTROL_CAMERA) && llGetAgentSize(pilot)!=ZERO_VECTOR) //パイロットがいて、カメラコントロールがある場合だけ制御開始します。
{
list _rules=[
CAMERA_ACTIVE,TRUE,
CAMERA_BEHINDNESS_ANGLE ,0.0,
CAMERA_BEHINDNESS_LAG,0.3,
CAMERA_FOCUS_LAG,0.3,
CAMERA_FOCUS_THRESHOLD,0.0,
CAMERA_DISTANCE,3.0,
CAMERA_PITCH,5.0,
CAMERA_FOCUS_LOCKED, FALSE,
CAMERA_POSITION_LAG,0.6,
CAMERA_POSITION_THRESHOLD,0.0,
CAMERA_FOCUS_OFFSET,<0,0,0>
];
llClearCameraParams();
llSetCameraParams(_rules);
}
}
else
{
//camonがFALSE⇒コントロールなし
llClearCameraParams();
}
}
default
{
state_entry()
{
//初期化イベント
llSitTarget(<0.0,0.0,0.5>,ZERO_ROTATION); //アバターの座る位置
llSetClickAction(CLICK_ACTION_SIT); //クリックしたときの動作を「座る」にします。
llSetCameraEyeOffset(<-5.0,0.0,1.0>); //座った時のカメラの位置を指定します。
llSetCameraAtOffset(<2.0,0.0,0.0>); //座った時にカメラが見ている位置を指定します。
llSetStatus(STATUS_PHYSICS,FALSE); //物理をオフにします。
planeEngine();
}
on_rez(integer start_param)
{
init();
}
changed(integer change)
{
//プリムやスクリプトに状態変化があった場合のイベント
if (change & CHANGED_LINK)
{
//リンクが変更になった
key _av=llAvatarOnSitTarget(); //座っているアバターのUUIDを取得します。
if (_av!=NULL_KEY) //NULL_KEYでない⇒誰かが座っている。
{
if (pilot==NULL_KEY) //pilotがNULL_KEY⇒誰かが初めて座った。
{
pilot=_av; //pilotに座った人のUUIDを設定
llRequestPermissions(pilot,PERMISSION_CONTROL_CAMERA | PERMISSION_TAKE_CONTROLS); //カメラ操作とパイロットのキーやマウス操作の監視の権限を要求します
llListenRemove(handle); //今まで聞いていたかもしれないListenをやめます。
handle=llListen(0,"",pilot,""); //パイロットのチャット発言の傍受を開始します。
}
}
else //座っているアバターのUUIDがNULL_KEYなら誰かが立ち上がったか、または最初から座っていません。
{
init();
}
}
}
run_time_permissions(integer permissions)
{
//権限が許可または不許可であった場合に発生するイベント
if (permissions & PERMISSION_TAKE_CONTROLS) //アバターがキーやマウス操作の監視を許可した場合
{
//各種のキー操作の監視と、通常の動作の停止を要求します
llTakeControls(CONTROL_UP | CONTROL_DOWN | CONTROL_FWD | CONTROL_BACK | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT | CONTROL_ML_LBUTTON | CONTROL_LBUTTON, TRUE, FALSE);
llSetStatus(STATUS_PHYSICS,TRUE); //物理をオンにします。
}
if (permissions & PERMISSION_CONTROL_CAMERA) //アバターがカメラコントロールを許可した場合
{
setCamera(); //カメラ状態を反映させます。(初期値は操作なし)
}
}
listen(integer channel, string name, key id, string message)
{
string _command=llToLower(message); //半角アルファベットをすべて小文字にします
if (_command=="c" || _command=="c" || _command=="C")
{
//コマンド”C”。飛行機では一般的にこのコマンドはカメラ操作に割り当てられます。
camon=!camon; //カメラ状態を現在と逆にします。
setCamera(); //カメラ状態を反映させます。
}
}
control(key name, integer keyPress, integer edges)
{
//llTakeControls()で要求したキー・マウス操作が行われた場合に発生するイベント
integer _keyDown=keyPress & edges; //押されているキーのうちで状態が変ったキーは今押され始めたキーです。keyPressとedgesのビット論理和(AND)を取ると取得できます。
integer _keyUp=~keyPress & edges; //押されているキーの逆のうちで状態が変ったキーは今離されたキーです。keyPressのビット反転とedgesのANDを取ると取得できます。


//--------------------------------------------------------
//スロットル(前進速度)
//PgUp(CONTROL_UP)で増速、PgDwn(CONTROL_DOWN)で減速します。
//--------------------------------------------------------
if (keyPress & CONTROL_UP) throttle=throttle+0.01; //この書き方もできるし。。
if (keyPress & CONTROL_DOWN) throttle-=0.01; //この書き方も出来ます。
if (throttle>1.0) throttle=1.0; //最大を超えそうなら最大にします。
else if (throttle<0.0) throttle=0.0; //最少を下回りそうなら最小にします。

//--------------------------------------------------------
//エルロン(ロール・左右傾斜)
//←→キー(CONTROL_ROT_LEFT/CONTROL_ROT_RIGHT)で操作します。
//--------------------------------------------------------
if (keyPress & CONTROL_ROT_LEFT) angular_motor.x-=0.1;
if (keyPress & CONTROL_ROT_RIGHT) angular_motor.x+=0.1;
if (_keyUp & CONTROL_ROT_LEFT) angular_motor.x=0.0; //飛行機では通常、キーを離したらならすぐに回転力をゼロにリセットします。
if (_keyUp & CONTROL_ROT_RIGHT) angular_motor.x=0.0;
if (angular_motor.x>1.0) angular_motor.x=1.0; //最大を超えそうなら最大にします。
else if (angular_motor.x<-1.0) angular_motor.x=-1.0; //最少を下回りそうなら最小にします。

//--------------------------------------------------------
//エレベーター(ピッチ・上下首ふり、水平尾翼)
//↑↓キー(CONTROL_FWD/CONTROL_BACK)で操作します。
//飛行機スクリプトでは慣習的に↑キーで機首下げです。
//↓キーで機首上げです。
//--------------------------------------------------------
if (keyPress & CONTROL_FWD) angular_motor.y+=0.1;
if (keyPress & CONTROL_BACK) angular_motor.y-=0.1;
if (_keyUp & CONTROL_FWD) angular_motor.y=0.0;
if (_keyUp & CONTROL_BACK) angular_motor.y=0.0;
if (angular_motor.y>1.0) angular_motor.y=1.0; //最大を超えそうなら最大にします。
else if (angular_motor.y<-1.0) angular_motor.y=-1.0; //最少を下回りそうなら最小にします。

//--------------------------------------------------------
//ラダー(ヨー・左右首ふり、垂直尾翼)
//SHIFT+←→キー(CONTROL_LEFT/CONTROL_RIGHT)で操作します。
//--------------------------------------------------------
if (keyPress & CONTROL_LEFT) angular_motor.z+=0.1;
if (keyPress & CONTROL_RIGHT) angular_motor.z-=0.1;
if (_keyUp & CONTROL_LEFT) angular_motor.z=0.0;
if (_keyUp & CONTROL_RIGHT) angular_motor.z=0.0;
if (angular_motor.z>1.0) angular_motor.z=1.0; //最大を超えそうなら最大にします。
else if (angular_motor.z<-1.0) angular_motor.z=-1.0; //最少を下回りそうなら最小にします。

llSetForce(<0.0,0.0,llGetMass()*9.8*throttle>,TRUE); //揚力を設定
//速度の最大値を27.0m/sで、それに0.0~1.0をかけて設定します。
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<27.0*throttle,0.0,0.0>);
//ロール、ピッチ、ヨー回転にそれぞれ最大値に現在の状態をかけて設定します。
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<10.0*angular_motor.x,1.0*angular_motor.y,0.5*angular_motor.z>);
}
}



説明が舌足らずな部分もあるかと存じますが、パラメーターを色々いじって調整して体感する方が早いと思います。
次回は、タイマーを組み込んでもう少し細かく挙動を調整する方法を書いてみたいと思います。


ひとつ前を読む
  
タグ :lsl飛行機


Posted by RBK Drachnyd(しお) at 21:04Comments(0)LSLで作る
2016年01月27日

飛行機をつくる:(2) カメラコマンドをつける

2回目は前回のなんちゃって飛行機にカメラ制御を実装します。

正確にはなんちゃって飛行機にも簡単な方のカメラ制御は既についていて、その部分は以下の2行(state_entry内)です。
llSetCameraEyeOffset(<-5.0,0.0,1.0>); //座った時のカメラの位置を指定します。
llSetCameraAtOffset(<2.0,0.0,0.0>); //座った時にカメラが見ている位置を指定します。
この二行は、座った時のカメラの位置と、座った時にカメラが見ている場所を指定しています。販売されている飛行機では必ずこの2つは指定されていて、デフォルトの状態ではこの設定が有効化されています。
今回はこの2行ではなくて、チャットコマンドの「C」で切り替わる事が多いダイナミックカメラを対象にします。

読者の対象としては「スクリプトをかじってはいるものの、どうやってサクサクと考えていけばいいのかの道筋が今一つ分からない方」を対象にします。つまり、スクリプター(またはところてん)が脳内で考えている事の暴露(笑)となります。

1:全体の計画


前回、スクリプトは常に「~したら**」する、という部品の集合体だと述べました。というより、その形をはっきりイメージしないとスクリプトは決して作れません。なので、まず最初にやるべきことをこの「~したら**」に従ってストーリーにします。
といってもそれほど難しい事ではなくて、よそ様(あるいは私やてっちゃん)が販売している飛行機に乗っていて普段している自分の事を言葉にして並べるだけです。例えば・・・
1)座る
2)スロットルを上げて飛ぶ
3)チャットに「c」と入れてカメラを好きな状態にする
4)飛び回る
最初はこの程度です。
このうち、カメラに関係ありそうなのは3)の部分だけなので、要するに「チャットでパイロットが「C」と喋った(他の人は無視)のを聴いたらカメラを切り替える」という機能を追加すればOK!という事です。
続いて、このストーリー3)について分からない部分をぐぐります。ここで一つコツというかお約束があります。それは、
必ず最初にリンデンの公式のLSL解説WIKIに目を通す
これがとても大事です。リンデンのサイトの場合ぐぐっても部品がヒットするだけで全体像が見えにくいのは確かなのですが、部品の説明に先に触れておき、触れる回数を増やしていくとサンプルの理解力が段々上がっていきます。また、サンプルは通常特定の事が出来る完成品として、それに関する説明しか書いてありませんが、リンデン公式の場合は下の方に「関連」や「警告(注意事項)」が書いてあったりして、今は関係ないものの見ておくと良い他の関連情報も見つけられます。

2:チャットを聞けるようにする


チャットを聞けるようになる方法が分からない場合は、まずはイベントを調べます。このページの中に登場しているリンク先はスクリで出来る「~したら」の全てで、これ以外の事はスクリでは原則出来ません
該当するのは「listen」イベントですので、「~したら」の部分はこれで行う事になります。つまり「listen」イベントで「C」を聴くことが出来る様になれば良いわけですね。答えはもうそこに書いてあります。
「チャットによって発生します。 llListen を使って開始と検索条件の設定を行います。」
だそうなので、次に「llListen」の説明を読みます。
ややこしい単語は無視して概要を総合すると、llListenという命令は、指定のチャットチャンネルで、指定の検索条件に合致する発言を聴く事を開始する、という命令です。
なので「チャットでパイロットが「C」と喋った(他の人は無視)のを聴いたらカメラを切り替える」に戻ると、まずは、
パイロットが座ったらllListenをチャンネルゼロ(普通のチャット)で唱える。
その時、パイロットだけを聴く対象にする。
という事になります。
聴くべき文字も指定できるのですが、パイロットが「c(半角小文字)」というか「C(半角大文字)」というか「C(全角大文字)」というか「c(全角小文字)」というか分かりませんので、聴くべき文字列は指定しません。ユーザーの利便性対応は大変です(笑)。
また、パイロットがいつ「C」と喋るかはパイロットの好き勝手ですので、パイロットが座ったら即座に聴くのを開始しないといけません。ですので、「~したら**」するをもう少し細かく変更します。つまり、
1)座る
2)座ったパイロットの発言を聞けるようにllListenを唱える
3)チャットで「c」が聞こえた(listenイベントが発生して発言が「c」だった)らカメラを何かする
という事になります。
自前でスクリプトを作るとはこんな感じで、最初に大雑把な「~したら**する」をイベントと処理の組み合わせに置き換えて、それを段々と細かくしていく作業に他なりません。
パイロットが座ったかどうかの判定はchangedイベントの中でしていますので、私なら下の様にします。
changed(integer change)
{
//プリムやスクリプトに状態変化があった場合のイベント
if (change & CHANGED_LINK)
{
//リンクが変更になった
key _av=llAvatarOnSitTarget(); //座っているアバターのUUIDを取得します。
if (_av!=NULL_KEY) //NULL_KEYでない⇒誰かが座っている。
{
if (pilot==NULL_KEY) //pilotがNULL_KEY⇒誰かが初めて座った。
{
pilot=_av; //pilotに座った人のUUIDを設定
llRequestPermissions(pilot,PERMISSION_CONTROL_CAMERA | PERMISSION_TAKE_CONTROLS); //カメラ操作とパイロットのキーやマウス操作の監視の権限を要求します
llListenRemove(handle); //追加:今まで聞いていたかもしれないListenをやめます。
handle=llListen(0,"",pilot,""); //追加:パイロットのチャット発言の傍受を開始します。

}
}
else //座っているアバターのUUIDがNULL_KEYなら誰かが立ち上がったか、または最初から座っていません。
{
init();
}
}
}
listen(integer channel, string name, key id, string message)
{
string _command=llToLower(message); //半角アルファベットをすべて小文字にします
if (_command=="c" || _command=="c" || _command=="C")
{
//コマンド”C”。飛行機では一般的にこのコマンドはカメラ操作に割り当てられます。
//ここで何かカメラを操作するか変更します
}
}

部分の抜粋ですので上だけでは動かないのですが、llListenを唱える前にllListenRemoveを唱えるのはお約束の構造です。何故そうしなければならないのかは考えてみてください。
listenイベントの冒頭で唱えているllToLower()は半角アルファベットを全て小文字にせよという命令です。一旦それで全ての半角文字を小文字にした後に、if (_command=="c" || _command=="c" || _command=="C")のところで「c(半角小文字)」または「c(全角小文字)」または「C(全角大文字)」だった場合は、と場合分けを入れています。「==」は等しい、「||」(SHIFT+¥を2回)は「または」の意味です。


3:カメラをくっつける


ではいよいよ、怪しげなカメラをくっつけます。「パイロットが座ったらコマンドを聞きはじめ、Cと聞いたらカメラ制御をする」というストーリでした。「Cと聞いたら」までは出来上がっているので、引き続きぐぐります
検索結果の中でまずはリンデンWIKIを開いてみます。すると、
「実行するには、llRequestPermissions による PERMISSION_CONTROL_CAMERA 権限が必要です。」
と書いてあります。この手の「権限が云々」という言葉がリンデンWIKIに出てくるときは、スクリがそれを行うにはアバターの許可が必要であるという意味で、その場合は必ずllRequestPermissions()を唱えます。
llRequestPermissions()を見ると、関係ありそうなのは「PERMISSION_CONTROL_CAMERA」です。権限の要求はパイロットが座った時にキー操作を要求していますので、その部分を書き換えてやればよい事が分かります。
llRequestPermissions(pilot,PERMISSION_CONTROL_CAMERA | PERMISSION_TAKE_CONTROLS);
こんな感じです。記号「|」はビット計算記号ですので、この場合「キー操作とカメラの制御」をパイロットに要求していることになります。これで準備はOKです。
続いて、「C」を聞いたら、の所にカメラ操作命令を入れてやります。直接そこに書き込んでも良いのですが、カメラ操作も意外と改造をしていくとあちこちで同じ処理をしたくなることが多いので、私はいつも関数としてスクリの上の方に書いておいています。listenの中はこんな感じです。
listen(integer channel, string name, key id, string message)
{
string _command=llToLower(message); //半角アルファベットをすべて小文字にします
if (_command=="c" || _command=="c" || _command=="C")
{
//コマンド”C”。飛行機では一般的にこのコマンドはカメラ操作に割り当てられます。
camon=!camon; //カメラ状態を現在と逆にします。
setCamera(); //カメラ状態を反映させます。
}
}


関数「setCamera()」の方はこんな感じです。
//-----------------------------------------
//動的カメラ設定関数 setCamera()
//-----------------------------------------
integer camon=FALSE; //カメラタイプ
setCamera()
{
if (camon)
{
//camonがTRUE⇒カメラコントロールあり
if ((llGetPermissions() & PERMISSION_CONTROL_CAMERA) && llGetAgentSize(pilot)!=ZERO_VECTOR) //パイロットがいて、カメラコントロールがある場合だけ制御開始します。
{
list _rules=[
CAMERA_ACTIVE,TRUE,
CAMERA_BEHINDNESS_ANGLE ,0.0,
CAMERA_BEHINDNESS_LAG,0.3,
CAMERA_FOCUS_LAG,0.3,
CAMERA_FOCUS_THRESHOLD,0.0,
CAMERA_DISTANCE,3.0,
CAMERA_PITCH,5.0,
CAMERA_FOCUS_LOCKED, FALSE,
CAMERA_POSITION_LAG,0.6,
CAMERA_POSITION_THRESHOLD,0.0,
CAMERA_FOCUS_OFFSET,<0,0,0>
];
llClearCameraParams();
llSetCameraParams(_rules);
}
}
else
{
//camonがFALSE⇒コントロールなし
llClearCameraParams();
}
}
llGetPermissions()は現在許可されている権限を持ってくる命令で、権限がちゃんと取れているか念の為確認している部分です。また「&&(AND、かつ、さらに)」に引き続く「llGetAgentSize(pilot)!=ZERO_VECTOR」の部分は、パイロットの身長を調べています。パイロットの身長が無い場合というのは、パイロットがSIMにいなくなってしまった状態(例えば落ちた)ような場合を意味しますので、要するに「アバターがちゃんといるなら」という意味になります。お約束の使い方です。
カメラの具体的なパラメーターは私が販売時に乗せている「シネマカメラ」と全く同じものです。この種のパラメーター設定をする物はパーティクルにしろカメラにしろ、理解するのに最も近道は具体的に数字を変えてみてどうなるかやってみる事です。カメラは簡単な方ですが、それでも説明を読んでも多分全く意味不明でしょうし、カメラを変えて飛行してみるだけで一日や二日は楽しく遊べます。
と、申しますか、是非遊んでみてください。カメラに凝った乗り物は意外と販売品でも少ないのですが、乗り物エンジンの方を全く変えなくても、カメラを変えるだけで乗り心地がガラリと変わって感じます。意外と腕の見せ所です。(↓例えばこんな感じです↓)

また、カメラパラメーターの変更でこの手の実験と結果の確認作業に慣れておくと、乗り物機能の複雑奇怪なパラメーターについても自分で調整して変更する作業の準備になります。SL内のこの場所に行くとゼロ戦と95式水上偵察機のデモ版が看板からREZ出来ます。コマンド「C」で3種類のカメラが両方に仕込んでありますので、カメラパラメーターと乗り物機能の設定差による、乗り味の違いを体験してみてください。シネマカメラは上と同じもので、ダイナミックカメラとカメラ操作なしモードは2機種で別のパラメーターになっています。

ということで、今回の完成状態は以下の枠内になりました。
key pilot=NULL_KEY; //パイロットのUUID
float throttle=0.0; //スロットル状態
vector angular_motor=ZERO_VECTOR; //舵操作状態
integer handle=0; //チャット傍受識別番号
integer camon=FALSE; //カメラタイプ
//-----------------------------------------
//初期化関数 init()
//-----------------------------------------
init()
{
llListenRemove(handle); //チャット傍受を解除します。
pilot=NULL_KEY; //pilotを初期化します。
llSetStatus(STATUS_PHYSICS,FALSE); //物理を切ってその場に停止させます。
camon=FALSE; //カメラタイプを初期化します。
}
//-----------------------------------------
//エンジン設定関数 planeEngine()
//-----------------------------------------
planeEngine()
{
llSetVehicleType(VEHICLE_TYPE_AIRPLANE); //乗り物タイプを飛行機にします。
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE,0.0); //舵操作への反応速度を最高感度にします。
}
//-----------------------------------------
//動的カメラ設定関数 setCamera()
//-----------------------------------------
setCamera()
{
if (camon)
{
//camonがTRUE⇒カメラコントロールあり
if ((llGetPermissions() & PERMISSION_CONTROL_CAMERA) && llGetAgentSize(pilot)!=ZERO_VECTOR) //パイロットがいて、カメラコントロールがある場合だけ制御開始します。
{
list _rules=[
CAMERA_ACTIVE,TRUE,
CAMERA_BEHINDNESS_ANGLE ,0.0,
CAMERA_BEHINDNESS_LAG,0.3,
CAMERA_FOCUS_LAG,0.3,
CAMERA_FOCUS_THRESHOLD,0.0,
CAMERA_DISTANCE,3.0,
CAMERA_PITCH,5.0,
CAMERA_FOCUS_LOCKED, FALSE,
CAMERA_POSITION_LAG,0.6,
CAMERA_POSITION_THRESHOLD,0.0,
CAMERA_FOCUS_OFFSET,<0,0,0>
];
llClearCameraParams();
llSetCameraParams(_rules);
}
}
else
{
//camonがFALSE⇒コントロールなし
llClearCameraParams();
}
}
default
{
state_entry()
{
//初期化イベント
llSitTarget(<0.0,0.0,0.5>,ZERO_ROTATION); //アバターの座る位置
llSetClickAction(CLICK_ACTION_SIT); //クリックしたときの動作を「座る」にします。
llSetCameraEyeOffset(<-5.0,0.0,1.0>); //座った時のカメラの位置を指定します。
llSetCameraAtOffset(<2.0,0.0,0.0>); //座った時にカメラが見ている位置を指定します。
llSetStatus(STATUS_PHYSICS,FALSE); //物理をオフにします。
planeEngine();
}
on_rez(integer start_param)
{
init();
}
changed(integer change)
{
//プリムやスクリプトに状態変化があった場合のイベント
if (change & CHANGED_LINK)
{
//リンクが変更になった
key _av=llAvatarOnSitTarget(); //座っているアバターのUUIDを取得します。
if (_av!=NULL_KEY) //NULL_KEYでない⇒誰かが座っている。
{
if (pilot==NULL_KEY) //pilotがNULL_KEY⇒誰かが初めて座った。
{
pilot=_av; //pilotに座った人のUUIDを設定
llRequestPermissions(pilot,PERMISSION_CONTROL_CAMERA | PERMISSION_TAKE_CONTROLS); //カメラ操作とパイロットのキーやマウス操作の監視の権限を要求します
llListenRemove(handle); //今まで聞いていたかもしれないListenをやめます。
handle=llListen(0,"",pilot,""); //パイロットのチャット発言の傍受を開始します。
}
}
else //座っているアバターのUUIDがNULL_KEYなら誰かが立ち上がったか、または最初から座っていません。
{
init();
}
}
}
run_time_permissions(integer permissions)
{
//権限が許可または不許可であった場合に発生するイベント
if (permissions & PERMISSION_TAKE_CONTROLS) //アバターがキーやマウス操作の監視を許可した場合
{
//各種のキー操作の監視と、通常の動作の停止を要求します
llTakeControls(CONTROL_UP | CONTROL_DOWN | CONTROL_FWD | CONTROL_BACK | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT | CONTROL_ML_LBUTTON | CONTROL_LBUTTON, TRUE, FALSE);
llSetStatus(STATUS_PHYSICS,TRUE); //物理をオンにします。
}
if (permissions & PERMISSION_CONTROL_CAMERA) //アバターがカメラコントロールを許可した場合
{
setCamera(); //カメラ状態を反映させます。(初期値は操作なし)
}
}
listen(integer channel, string name, key id, string message)
{
string _command=llToLower(message); //半角アルファベットをすべて小文字にします
if (_command=="c" || _command=="c" || _command=="C")
{
//コマンド”C”。飛行機では一般的にこのコマンドはカメラ操作に割り当てられます。
camon=!camon; //カメラ状態を現在と逆にします。
setCamera(); //カメラ状態を反映させます。
}
}
control(key name, integer keyPress, integer edges)
{
//llTakeControls()で要求したキー・マウス操作が行われた場合に発生するイベント
integer _keyDown=keyPress & edges; //押されているキーのうちで状態が変ったキーは今押され始めたキーです。keyPressとedgesのビット論理和(AND)を取ると取得できます。
integer _keyUp=~keyPress & edges; //押されているキーの逆のうちで状態が変ったキーは今離されたキーです。keyPressのビット反転とedgesのANDを取ると取得できます。


//--------------------------------------------------------
//スロットル(前進速度)
//PgUp(CONTROL_UP)で増速、PgDwn(CONTROL_DOWN)で減速します。
//--------------------------------------------------------
if (keyPress & CONTROL_UP) throttle=throttle+0.01; //この書き方もできるし。。
if (keyPress & CONTROL_DOWN) throttle-=0.01; //この書き方も出来ます。
if (throttle>1.0) throttle=1.0; //最大を超えそうなら最大にします。
else if (throttle<0.0) throttle=0.0; //最少を下回りそうなら最小にします。

//--------------------------------------------------------
//エルロン(ロール・左右傾斜)
//←→キー(CONTROL_ROT_LEFT/CONTROL_ROT_RIGHT)で操作します。
//--------------------------------------------------------
if (keyPress & CONTROL_ROT_LEFT) angular_motor.x-=0.1;
if (keyPress & CONTROL_ROT_RIGHT) angular_motor.x+=0.1;
if (_keyUp & CONTROL_ROT_LEFT) angular_motor.x=0.0; //飛行機では通常、キーを離したらならすぐに回転力をゼロにリセットします。
if (_keyUp & CONTROL_ROT_RIGHT) angular_motor.x=0.0;
if (angular_motor.x>1.0) angular_motor.x=1.0; //最大を超えそうなら最大にします。
else if (angular_motor.x<-1.0) angular_motor.x=-1.0; //最少を下回りそうなら最小にします。

//--------------------------------------------------------
//エレベーター(ピッチ・上下首ふり、水平尾翼)
//↑↓キー(CONTROL_FWD/CONTROL_BACK)で操作します。
//飛行機スクリプトでは慣習的に↑キーで機首下げです。
//↓キーで機首上げです。
//--------------------------------------------------------
if (keyPress & CONTROL_FWD) angular_motor.y+=0.1;
if (keyPress & CONTROL_BACK) angular_motor.y-=0.1;
if (_keyUp & CONTROL_FWD) angular_motor.y=0.0;
if (_keyUp & CONTROL_BACK) angular_motor.y=0.0;
if (angular_motor.y>1.0) angular_motor.y=1.0; //最大を超えそうなら最大にします。
else if (angular_motor.y<-1.0) angular_motor.y=-1.0; //最少を下回りそうなら最小にします。

//--------------------------------------------------------
//ラダー(ヨー・左右首ふり、垂直尾翼)
//SHIFT+←→キー(CONTROL_LEFT/CONTROL_RIGHT)で操作します。
//--------------------------------------------------------
if (keyPress & CONTROL_LEFT) angular_motor.z+=0.1;
if (keyPress & CONTROL_RIGHT) angular_motor.z-=0.1;
if (_keyUp & CONTROL_LEFT) angular_motor.z=0.0;
if (_keyUp & CONTROL_RIGHT) angular_motor.z=0.0;
if (angular_motor.z>1.0) angular_motor.z=1.0; //最大を超えそうなら最大にします。
else if (angular_motor.z<-1.0) angular_motor.z=-1.0; //最少を下回りそうなら最小にします。

llSetForce(<0.0,0.0,llGetMass()*9.8*throttle>,TRUE); //揚力を設定
//速度の最大値を27.0m/sで、それに0.0~1.0をかけて設定します。
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<27.0*throttle,0.0,0.0>);
//ロール、ピッチ、ヨー回転にそれぞれ最大値に現在の状態をかけて設定します。
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<10.0*angular_motor.x,1.0*angular_motor.y,0.5*angular_motor.z>);
}
}



次回は乗り物機能の細かいパラメーターを細かく調整できるように改造してみようと思います。

ひとつ前を読む
  
タグ :lsl飛行機


Posted by RBK Drachnyd(しお) at 03:49Comments(0)LSLで作る
2016年01月24日

飛行機をつくる:(1)~もっとも短い(?)飛行機のサンプル

スクリプトを担当させていただいているteCraftのてっちゃんがSLTVのインタビューで、「自分がスカイで作業せず、誰でも制作途中の状態が見れるようにしているのは、飛行機を作る仲間が増えると良いなと思っての事だ」とおっしゃっておられ、なるほどそういう意図でしたかと納得したので、飛行機を作る事をテーマにスクリプトについても若干書いてみようかなと思います。(なにしろスクリは作っているところを見せる事はできませんから!)
下のURLがてっちゃんの作業場です。インワールドのツールで造形をされているので、タイミングが合うと作り方を見ることが出来るでしょう。ほかのジャンルでも、ものづくりに興味がある方には参考になる事も多いかと存じます。
Hope Island/通称”てっちゃん城”または”てっちゃん御殿”

スクリなんて触ったことも無い!という方は対象にしませんので、多少大雑把な説明になるかもしれません。スクリを本当にこれから書いてみたい方はまずはBlack-Sheepさんの入門あたりをざっとご覧ください。サンプルも豊富でまとまっています。

さて、早速手始めに、下の枠内のスクリプトが飛行機のスクリプトのもっとも基本的な形だと思います。100行ちょっとの短いスクリプトですが、下の動画の様に、この程度でもそれなりに飛行機してくれます。

key pilot=NULL_KEY; //パイロットのUUID
float throttle=0.0; //スロットル状態
vector angular_motor=ZERO_VECTOR; //舵操作状態
//-----------------------------------------
//初期化関数 init()
//-----------------------------------------
init()
{
pilot=NULL_KEY; //pilotを初期化します。
llSetStatus(STATUS_PHYSICS,FALSE); //物理を切ってその場に停止させます。
}
//-----------------------------------------
//エンジン設定関数 planeEngine()
//-----------------------------------------
planeEngine()
{
llSetVehicleType(VEHICLE_TYPE_AIRPLANE); //乗り物タイプを飛行機にします。
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE,0.0); //舵操作への反応速度を最高感度にします。
}
default
{
state_entry()
{
//初期化イベント
llSitTarget(<0.0,0.0,0.5>,ZERO_ROTATION); //アバターの座る位置
llSetClickAction(CLICK_ACTION_SIT); //クリックしたときの動作を「座る」にします。
llSetCameraEyeOffset(<-5.0,0.0,1.0>); //座った時のカメラの位置を指定します。
llSetCameraAtOffset(<2.0,0.0,0.0>); //座った時にカメラが見ている位置を指定します。
llSetStatus(STATUS_PHYSICS,FALSE); //物理をオフにします。
planeEngine();
}
on_rez(integer start_param)
{
init();
}
changed(integer change)
{
//プリムやスクリプトに状態変化があった場合のイベント
if (change & CHANGED_LINK)
{
//リンクが変更になった
key _av=llAvatarOnSitTarget(); //座っているアバターのUUIDを取得します。
if (_av!=NULL_KEY) //NULL_KEYでない⇒誰かが座っている。
{
if (pilot==NULL_KEY) //pilotがNULL_KEY⇒誰かが初めて座った。
{
pilot=_av; //pilotに座った人のUUIDを設定
llRequestPermissions(pilot,PERMISSION_TAKE_CONTROLS); //パイロットのキーやマウス操作の監視の権限を要求します
}
}
else //座っているアバターのUUIDがNULL_KEYなら誰かが立ち上がったか、または最初から座っていません。
{
init();
}
}
}
run_time_permissions(integer permissions)
{
//権限が許可または不許可であった場合に発生するイベント
if (permissions & PERMISSION_TAKE_CONTROLS) //アバターがキーやマウス操作の監視を許可した場合
{
//各種のキー操作の監視と、通常の動作の停止を要求します
llTakeControls(CONTROL_UP | CONTROL_DOWN | CONTROL_FWD | CONTROL_BACK | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT | CONTROL_ML_LBUTTON | CONTROL_LBUTTON, TRUE, FALSE);
llSetStatus(STATUS_PHYSICS,TRUE); //物理をオンにします。
}
}
control(key name, integer keyPress, integer edges)
{
//llTakeControls()で要求したキー・マウス操作が行われた場合に発生するイベント
integer _keyDown=keyPress & edges; //押されているキーのうちで状態が変ったキーは今押され始めたキーです。keyPressとedgesのビット論理和(AND)を取ると取得できます。
integer _keyUp=~keyPress & edges; //押されているキーの逆のうちで状態が変ったキーは今離されたキーです。keyPressのビット反転とedgesのANDを取ると取得できます。


//--------------------------------------------------------
//スロットル(前進速度)
//PgUp(CONTROL_UP)で増速、PgDwn(CONTROL_DOWN)で減速します。
//--------------------------------------------------------
if (keyPress & CONTROL_UP) throttle=throttle+0.01; //この書き方もできるし。。
if (keyPress & CONTROL_DOWN) throttle-=0.01; //この書き方も出来ます。
if (throttle>1.0) throttle=1.0; //最大を超えそうなら最大にします。
else if (throttle<0.0) throttle=0.0; //最少を下回りそうなら最小にします。

//--------------------------------------------------------
//エルロン(ロール・左右傾斜)
//←→キー(CONTROL_ROT_LEFT/CONTROL_ROT_RIGHT)で操作します。
//--------------------------------------------------------
if (keyPress & CONTROL_ROT_LEFT) angular_motor.x-=0.1;
if (keyPress & CONTROL_ROT_RIGHT) angular_motor.x+=0.1;
if (_keyUp & CONTROL_ROT_LEFT) angular_motor.x=0.0; //飛行機では通常、キーを離したらならすぐに回転力をゼロにリセットします。
if (_keyUp & CONTROL_ROT_RIGHT) angular_motor.x=0.0;
if (angular_motor.x>1.0) angular_motor.x=1.0; //最大を超えそうなら最大にします。
else if (angular_motor.x<-1.0) angular_motor.x=-1.0; //最少を下回りそうなら最小にします。

//--------------------------------------------------------
//エレベーター(ピッチ・上下首ふり、水平尾翼)
//↑↓キー(CONTROL_FWD/CONTROL_BACK)で操作します。
//飛行機スクリプトでは慣習的に↑キーで機首下げです。
//↓キーで機首上げです。
//--------------------------------------------------------
if (keyPress & CONTROL_FWD) angular_motor.y+=0.1;
if (keyPress & CONTROL_BACK) angular_motor.y-=0.1;
if (_keyUp & CONTROL_FWD) angular_motor.y=0.0;
if (_keyUp & CONTROL_BACK) angular_motor.y=0.0;
if (angular_motor.y>1.0) angular_motor.y=1.0; //最大を超えそうなら最大にします。
else if (angular_motor.y<-1.0) angular_motor.y=-1.0; //最少を下回りそうなら最小にします。

//--------------------------------------------------------
//ラダー(ヨー・左右首ふり、垂直尾翼)
//SHIFT+←→キー(CONTROL_LEFT/CONTROL_RIGHT)で操作します。
//--------------------------------------------------------
if (keyPress & CONTROL_LEFT) angular_motor.z+=0.1;
if (keyPress & CONTROL_RIGHT) angular_motor.z-=0.1;
if (_keyUp & CONTROL_LEFT) angular_motor.z=0.0;
if (_keyUp & CONTROL_RIGHT) angular_motor.z=0.0;
if (angular_motor.z>1.0) angular_motor.z=1.0; //最大を超えそうなら最大にします。
else if (angular_motor.z<-1.0) angular_motor.z=-1.0; //最少を下回りそうなら最小にします。

llSetForce(<0.0,0.0,llGetMass()*9.8*throttle>,TRUE); //揚力を設定
//速度の最大値を27.0m/sで、それに0.0~1.0をかけて設定します。
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<27.0*throttle,0.0,0.0>);
//ロール、ピッチ、ヨー回転にそれぞれ最大値に現在の状態をかけて設定します。
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<10.0*angular_motor.x,1.0*angular_motor.y,0.5*angular_motor.z>);
}
}





スクリプトのテストは簡単です。何か適当なプリムを作って、中に新規スクリプトを作り、上の枠内の全てをペーストして保存し、座ると起動します。
前後左右の矢印キーで上下左右、PageUpとPageDownキーで速度が増減します。

じっくり見るには上の枠内では読みにくいと思いますので、LSLエディターをダウンロードして起動した後に、枠内をコピー&ペーストし、CTRL+Dキーを押して整形してください。F6キーを押して、「LSL Syntax seems OK(LSLの文法は見たところOKだ!)」とダイアログが出れば成功です。

ではさっそく、上から順に中身を見ていきます。



key pilot=NULL_KEY; //パイロットのUUID
float throttle=0.0; //スロットル状態
vector angular_motor=ZERO_VECTOR; //舵操作状態
//-----------------------------------------
//初期化関数 init()
//-----------------------------------------
init()
{
pilot=NULL_KEY; //pilotを初期化します。
llSetStatus(STATUS_PHYSICS,FALSE); //物理を切ってその場に停止させます。
}
//-----------------------------------------
//エンジン設定関数 planeEngine()
//-----------------------------------------
planeEngine()
{
llSetVehicleType(VEHICLE_TYPE_AIRPLANE); //乗り物タイプを飛行機にします。
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE,0.0); //舵操作への反応速度を最高感度にします。
}

オレンジ色の部分は「グローバル変数」というものを「これらを使います」と宣言している部分です。グローバル(global)とは「地球全体の,世界的な,グローバルな」といった意味ですが、つまりこのスクリの中であればどこであっても使える変数、という意味です。「=」記号は「等しい」ではなく、「代入しなさい」という命令です。スクリの中での「等しい」は「==」と=記号を二つ並べます。
次に来る白色の部分は「関数」という物を宣言しています。形式は単純で、

名前(必要なら引数)
{
中身いろいろ
}

という形をとります。高校生の頃に(いやいやながら)勉強した数学の関数「y=f(x)」とか、「z=f(x,y)」とかいうあれと同じで、名前を決めてその中身で行う計算を定義しています。本当に名前を「f」とか「g」とか数学の教科書の様にしても良いのですが(笑)、後からみて分かるように何をするものであるのか名前を工夫しておくのが普通です。
一度このようにして冒頭に作っておくと、スクリのなかではどこであっても、名前(引数があるなら値)と名前と引数を与えてやれば、いつでも呼び出して実行が出来るようになります。
このスクリでは無理に作る必要もないのですが、後々何度も使いそうな定型の処理は関数化しておくと直すのが楽です。
「//」とスラッシュを二つ並べた以降は、改行されるまでは実行されないメモになります。このスクリでは少しやりすぎですが、こうやって作っている時に「//なんだかメモ」というのをこまめに書き残しておくと、後々改造する時に自分が何をしたくてこうやったのかを自分宛のメモとして残しておくことが出来ます。(経験的に2か月もするとすっかり忘れてしまいます!)

init()
名前の通り、スクリで使う変数やパラメーターを初期化する内容を集めておくのに作りました。今は不要ですが、後々例えば音を再生したり、着陸したら車スクリと同じ動きをするように変化させたり改造していくと、パイロットが降りたりエンジンを停止させたりした時にスクリを初期状態に戻したくなる事が幾つものタイミングであるはずなので、同じ処理をしそうな初期化はあらかじめ全部ここにまとめておく、という前提で用意しました。今のところは内容的にはパイロットのUUIDをNULL_KEY(無効)に設定し、物理プリムである事をやめて通常のプリムに戻しています。

planeEngine()
飛行機として飛ぶことが出来る様に、スクリの「乗り物設定」をしている部分です。最も単純な飛行機スクリに必要な乗り物設定はこの二つだけです。手始めに「VEHICLE_TYPE_AIRPLANE」つまり「乗り物タイプは飛行機」を設定し、引き続き「VEHICLE_ANGULAR_MOTOR_TIMESCALE」をゼロつまり「乗り物の回転操作の反応感度を可能な限り今すぐ」に書き換えています。


default
{


  (なんだか色々)


}


この「default」の部分の{から}までの中身が、具体的なスクリの動作を書く部分になります。「default」とは「デフォルトの状態」を書く部分で、スクリの中に必ず一つなければなりません。ほかの「状態」を作る事も出来るのですがよっぽど特殊な事でなければ作る必要が無いので、「全体で使う変数と関数以外はdefaultの中に書くものだ」というお約束で十分です。
default{ }の中にはさらに{と}で開始と終了を記した、「state_entry()」や「changed()」といった大きなブロックが内蔵されています。これらは用語では「イベント」と呼ばれていて、このスクリの場合は図にすると下の様になります。



セカンドライフのスクリは全てこのような「~したら中身を実行する」という部品の中に、「その状態が発生したら実行」する内容を記述していくことになります。
スクリプトを自由に書けるレベルの人はこの「~したら**する」という物を上の図のような平面図だけではなく、関係性や順序でもイメージします。(本当に慣れてくると関係図が"見え”ます。つまり、脳の視覚野を本当に使っているのだと思います)
例えばこの飛行機の場合は、

0)スクリが保存されたりREZされたりしたら最初の設定をする
1)人が座る⇒キー操作の受付開始
2)人がキー操作取得を許可⇒物理にして動けるようにする
3)キー操作をした⇒旋回やスピードの変更を実行
4)人が立ち上がった⇒乗り物として動くことをやめて初期化

というストーリーがまず思い描かれます。そこでそれらに使えそうなイベントを下のURLで探すと、該当するものがこのスクリに登場するイベントである、という事になりますので、具体的にそれらの中に役割分担を割り振って書いていく事になります。
http://wiki.secondlife.com/wiki/Category:LSL_Events/ja




図にしてみると上の図のようになっていて、実行に順序があるのは「座った(control)」から「許可された(run_time_permissions)」の所だけで、他はいつでも起こり得る独立した要素になっています。乗り物スクリは車でも船でも、原理的には上の図のような構造になっているのですが、ある程度のレベルのスクリプターは常にこのような図のどの要素で何を行わせればよいのかを、作りたい事を要素に分解して思い描いています。これを思い描けるかどうかが好きな物を自由に作れるか、の分かれ目になります。
スクリで何かを自由に作れるレベルになりたい場合は、まずはLSLのイベントは丸暗記出来るまで何度も読み返して記憶すべきです。何故なら、イベントの種類と内容を知っているだけで「~したら**する」の「~したら」の部分は全部知っていることになるからです。後半の「**する」の部分はそれだけを”Google”ればサンプルスクリはたくさん見つかりますので、見つけたサンプルを抜粋してイベントの中に詰め込んでいく事になります。


state_entry
スクリが保存されたかリセットされた時にだけ行えばよい初期設定をまとめています。具体的には、アバターが座った時の位置を指定し(着席が出来るようにし)、マウスを乗せたときのアイコンが椅子マークになるようにし、座った時のカメラ位置を指定し、念の為物理を切り、冒頭で作った関数planeEngine()を実行して乗り物設定に飛行機を設定させています。
後は、プリムを物理にすれば飛行機になりますし、物理を切ればその場で停止してくれます。準備完了です。

on_rez
例えば飛行中に「取る」メニューでテイクされた場合などには飛行中の状態が残っているので、REZされた際には関数init()を実行して念の為初期化、という事を行っています。llResetScript()を使ってスクリ自体をリセットしてしまっても今の場合は良いのですが、ユーザー設定を記憶させておくなどの要素が使えなくなってしまうので、乗り物の場合はリセットよりも自分で初期化すべきものを初期化してやる方が良い気がします。

changed
if (change & CHANGED_LINK)
{
  云々・・・
}
となっていますが、この「if (change & CHANGED_LINK)」は「もし、プリムのリンクが変化したら」を意味します。
LSLではifは、「(」から「)」の中身の計算結果がゼロであれば次の{から}の中身は実行されず、ゼロ以外(マイナスもOK)であれば実行されるという場合分けになります。
記号「&」はビット演算子と言われる計算記号で、+-×÷と同じような数式の記号です。Windowsの電卓を起動して「表示(V)→プログラマ(P)」として、適当な数字を入力した後に「2進」を選ぶと0と1が並びます。いわゆる二進数ですが、「&」は、数字をこのような2進数にした時に、二つの数字の間で両方とも1である場所は1、片方または両方が0である場所は0にした数字を計算します。例えば、数字の7は「0111」、数字の13は「1101」なので、「&」の結果は「0101」つまり5になります。
LSLのchangedイベントでは、イベント引数の変数changeとCHANGED_LINKとの&計算が0でない場合にはリンクが変更されたという意味になります。また、アバターがプリムに座るとアバターは座ったプリムにリンクされますので、誰かが座った場合にはリンクが変化し、この部分が実行されます。
llAvatarOnSitTarget()を実行した結果がNULL_KEYでない場合は誰かが座ったという事ですので、一旦llAvatarOnSitTarget()の実行結果をUUIDを保存する変数_avに設定して、「_av!=NULL_KEY」で確認しています。「!=」は「等しくない」という比較計算を表す記号ですので、つまり「変数_avはNULL_KEY(無効)」でない⇒「誰か座っている」という意味になります。
この変数_avの様に、スクリの冒頭で使う事を宣言せず、イベントの中など含まれている領域で使用を宣言された変数は「ローカル変数」と言います。自分を囲んでいる{と}の間でだけ有効で、その外側では使えません。
_avが無効でない事を確認した後にさらに、「pilot==NULL_KEY」で変数「パイロット」が無効である場合だけという条件を規定しています。現在のこの短いスクリでは不要なのですが、二人乗りの飛行機にしたい!とか後々の改造の場合に効いてくる(かもしれない)お約束の手順です。
そして、_avが無効(NULL_KEY)でない場合だけ、llRequestPermissionsを唱えてキー操作の監視の許可を要求しています。
その後に出てくる「else」は、「そうでなければ」の意味で、「if (_av!=NULL_KEY)」と対になっています。つまり、_av!=NULL_KEY(誰か座っている)が正しい間はelse以後は実行されませんが、誰も座っていないのにリンクが変更になるとこの「else」以後が実行されます。内容的にはスクリの冒頭で作っておいた関数init()をここでも実行し、スクリのパラメーターを初期化させています。on_rezでもinit()を呼び出しています。このように同じことをあちこちでさせたい場合には関数を上の方で書いておくと、関数だけいじれば全体に反映される、という後々の修正の楽さを確保できます。

run_time_permissions
キー操作の許可が得られるとこのイベントが実行されるので、llTakeControls()を唱えて監視したいキー操作項目を指定します。記号「|」(SHIFT+¥)は「&」と同じくビット演算子で、こちらはいずれか片方が1である部分を1にした数字を計算します。
また、物理をここでオンにして、state_entryでplaneEngineを実行して設定しておいた乗り物設定が有効になります。

control
ユーザーが行ったキー操作を具体的に解釈して飛行機として作動させている中心部です。
integer _keyDown=keyPress & edges; //押されているキーのうちで状態が変ったキーは今押され始めたキーです。keyPressとedgesのビット論理和(AND)を取ると取得できます。
integer _keyUp=~keyPress & edges; //押されているキーの逆のうちで状態が変ったキーは今離されたキーです。keyPressのビット反転とedgesのANDを取ると取得できます。

この部分はコメントにある通り、「今押されたキー」と「今押すのをやめたキー」を計算で割り出しています。controlイベントではkeyPressの位置の引数に現在押されているキーが、edgesの位置の引数には変化があったキーが格納されて呼び出されてきます。また記号「~」は&と同じくビット計算で、0と1を全てのビット位置で逆転させる計算をします。なので、「keyPress & edges」とは、「現在押されていて変化があったキー」のビット位置だけが1になる計算ですし、「~keyPress & edges」は「現在押されているキーでないキーで変化があったキー」のビット位置だけが1になる計算になります。つまり前者は、「今押されたキー」ですし、後者は「今押すのをやめたキー」の意味になります。使う使わないはともかくとして、この2者の計算も乗り物ではお約束ですので、changedイベントの冒頭でとりあえず計算しておきます。


以後の部分はコメントメモにある通り具体的に速度や舵の操縦状態の解釈になっているのですが、このスクリプトでは小数点付数字(float)の変数trottleに0~1の数字を、また、三次元vectorの変数angular_motorのx、y、zの各軸に0~1の値を設定しています。この意図は、0=0%、1=100%という意味です。このようにしておき、最後の部分の
//速度の最大値を27.0m/sで、それに0.0~1.0をかけて設定します。
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,<27.0*throttle,0.0,0.0>);
//ロール、ピッチ、ヨー回転にそれぞれ最大値に現在の状態をかけて設定します。
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,<10.0*angular_motor.x,1.0*angular_motor.y,0.5*angular_motor.z>);

の所で乗り物機能に速度と回転を指定しています。
最初から最大値~最小値までを足したり引いたりしても良いのですが、そういう風にするとこのchangedイベントの中にあるキー操作の解釈のif文全部を書き換えないと後で微調整が出来ません。乗り物は特に作った後の微調整が勝負を決めるスクリになりがちですので、このタイプの、

とりあえず0~1の間の値を入れておいて最後に最大値をかけて反映する

というパターンはお約束のテクニックとして覚えておくと良いと思います。
もう少し詳しくいうと、これは「線形補間」というテクニックの省略された姿で、線形補間の計算式の本来の姿は、

中間結果=(1.0-T)×最小値+T×最大値

という形で、変数Tは0~1を取ります。Tがゼロの時は最小値になり、Tが1の時には最大値になるようにして中間の状態も作れる形式で、今の場合は最小値はゼロなので前半が省略された形になっている、という事です。



さて、このスクリが特徴的な行がたった一つだけあります。それは、

llSetForce(<0.0,0.0,llGetMass()*9.8*throttle>,TRUE); //揚力を設定

という命令です。llSetForce()はプリムにちからをかけ続ける命令なのですが、関数の内容を日本語で言うと、「自分の真上方向に重さ×9.8×スロットルの値分の力をかけ続けなさい」という意味になっています。9.8は高校で習った重力加速度そのもので、これに重さがかかりますので、結局、スロットルが100%で飛行機が水平なら重力による力と反対方向に重力と同じだけの力をかけ続けなさい、という命令になっています。
殆どの飛行機スクリのサンプルではこの命令の代わり重力を小さくする命令を使っていて、実際にその方がこんな余計な計算をしなくて済む分簡単になります。
では、何故自分の上方向に力をかけるのでしょうか?背面になれば重力が倍になるのに??
こういう小さなところにちょっとしたアレンジが入るだけでも、個性的な動き(味付け)をした乗り物が作れます。私の判断ではこの理由でこちらの方が良いと思っています。

貴方なら、どんな味付けにしますか?




次回はこのスクリプトにもう少し高度なカメラ操作をつけてみることにします。

次を読む
  


Posted by RBK Drachnyd(しお) at 23:46Comments(0)LSLで作る
2015年12月17日

零式艦上戦闘機21型フリーRezzer設置





というわけで。。
誰でも乗って遊べるデモ機のRezzerを設置しました。
SLURLは↓ここです。

http://maps.secondlife.com/secondlife/Jadu/4/22/31

看板をタッチするとREZされてすぐ乗って飛び立てますがその前に注意事項
この飛行機はスロットルが普通と違って速度を表していません。本当に馬力そのものを表しています。なので、滑走路に移動して十分な滑走を行わないと慣れるまでは浮き上がってもすぐ地面に逆戻りします。
一旦飛び上がってしまえばそんなに極端に落ちたがることはありませんが、挙動はYoutubeにある現実の52型ゼロ戦の映像とほぼ一緒の動きをします。デフォルメはしているので左右の旋回半径は小さいですが、上下については傾けると情け容赦なく落下しますので、既存の他メーカー製飛行機に乗り慣れている方は注意して感覚を確かめてください。舐めてかかると他人に突っ込んで叱られます。(笑)

飛行機に一度も乗ったことが無い方は、まず右クリックでFlyを選択して乗り込み、しばらく放置してください。エンジンスタートのアニメが全部終わると、←→の矢印キーで左右に首が振れるようになるので、そうなったら、チャットに「c(Enter)」を二回入れます。
「Cinema camera On」と表示されて機体がぐーっとカメラに寄ってきますので、その状態になったらPgUpキーを押すと前進します。PgDownキーを押すと減速します。左右キーとPgUpDwnキーで方向と速度を調整しながら、左手にある滑走路へ向かいます。移動中路面に書いてあるラインに従って移動すると定位置に配置できます。この飛行場では東から西(Rezzerと反対側の滑走路端部から加速開始して、Rezzerがあった側で離陸)がマナーなので、少々距離がありますが移動して滑走路に行ってください。
移動完了して滑走路方向に向き直ったら、何も考えずにPgUpを押し続け、推力100%まで上げてください。その後放置しておくと徐々におしりが持ち上がり、ふわりと浮きあがります。機首上向きは↓、機首下向きは↑を押します(イメージとは逆ですね)。機体が上昇していこうとすると上に、落っこちていこうとしていると下に移動しますし、速度が落ちればカメラに近づき、速度が上がれば遠ざかります。墜落しないように慎重にキーを操作して飛行してください。

タイヤはチャットで「g」と入れてやると出したりひっこめたりします。立ち上がるとその場で消えるので、飽きたら乗り捨ててください。


設定がぬるすぎて退屈だ!というM(シミュレーター志向)な方は、チャットで「mc」コマンドを入力してからマウスルックにしてみてください。スロットル操作のPgUpDownは変わりませんが、マウスルック時カメラの方向が操縦かんになります。このモードの難易度は恐らくSL最強レベルです(笑)。
その他の細かい操作やチャットコマンドは以下に製品版のノート内容を書き込んでおきますので、必要があれば読んでください。色々ごちゃごちゃと詰め込まれていて、Vice/Tcs(戦闘)系以外のコマンドはデモ機でもフルバージョンで動きます。

----------------------------------------------------------------------------------------------


+--------------------------------------------------------------------+
大日本帝国海軍
零式艦上戦闘機二一型(中島飛行機製造)ユーザーガイド
** CAUTION! 注意!**
この航空機のスロットルは速度を表しません。出力馬力と加速力を表します。
コマンド類や操作は代表的なエンジンを継承していますが、
このノートを読み、操縦を試して特徴の違いを体験してください。
******************
+--------------------------------------------------------------------+


~仕様~
ACM(空戦マニューバ)シミュレーター「Ptero」エンジン搭載。(下のガイドを必ずお読みください。クセが通常の航空機とかなり違います)
 VICE, TCS コンバットシステム搭載(VICE 7.7mmLMG×2丁(機首)、VICE CMB×4スロット(翼内20mm機銃) 、 TCS機銃)
 ゲストモード搭載。お友達に貸してあげることが出来ます。
 着地補助機能(デフォルトオン)。Pteroシミュレーターの重力・揚力計算を緩和して飛びやすくなります。
 自動フラップモード(デフォルトオン)。(離着陸揚力確保の自動補助およびベテラン級空戦フラップ操作の自動化)
 テクスチャー&色変更HUD搭載。貴方だけのカラーリングも可能です。
 エンジン・積載状態シミュレート。試作段階、真珠湾、歴史IF、神風など、さまざまな状態を演出します。当時のパイロットを偲んでください。
 アナログフライトスティック操作対応。(Windows7以降で専用ソフト使用時)



****************************************************
~離陸ガイド~(重要)
****************************************************
機体をREZして右クリックし、”Fly”を選択、搭乗します。
地上では非常に強力な重力がかかっているため、キーで操作が出来る様になった(エンジンがかかった)ら推力を100%まで上げて滑走路上で十分に加速してください。

低スロットルで離陸はほぼ不可能です。
何も考えずに100%まで推力を上げます。

HOLLYWOODやJapan airportなどの大型飛行場であれば、フラップを下げて(デフォルトの自動フラップオンならそのまま何もせず)100%で加速を続けていれば揚力が足りた時点で勝手に離陸します。
↓(エレベーター)操作で滑走距離は短縮されますが、操作が速すぎた場合は少し浮いた後上がらなくなります。慌てず↓キーを離して、機体が落ち着く様に少し待ちます。機首が下がり、加速が十分に行われて揚力が得られればふわりと安定して上昇を再開します。
「落ちちゃう!」と慌てて↓を押し続けるのは愉快な事になります。↓を離しても落下していくのはそもそも速度が足りていません。予科練(地上?)に戻って離陸をやりなおしましょう。

重力とエンジンを使って加速し、
速度で揚力を作り、
揚力で曲がり、
重力に逆らって減速する、

これらがこのエンジンの急所ですので、離陸に大半がつまっています。


充分に浮き上がると離陸完了して、(指定を切っていなければ)着陸アシスト機能がオンになります。gコマンドで車輪を収納して、離陸完了です。

はじめのうちはカメラはシネマカメラ(チャットでcコマンドを二回)を推奨します。速度が上がると機体が離れていき、速度が落ちれば近づいてきます。また、浮こうとしていれば機体が上に、落ちようとしていれば機体が下に下がりますので、自分がどうなっているのかが良く分かります。
フライトゲームで慣れている方はマウスルックでもOK!当時の海軍式の単位系ですが、メーターで状態は分かります。



****************************************************
~飛行について~
****************************************************
着陸アシストがオンの状態(デフォルト)では、水面高度100メートルを基準にして、下がれば下がるほど重力が小さくなります。(水面高度0ではスロットル30%を超えていれば実質無重力)
アシスト機能のオンオフに関わりなく、100メートルより上では重力は常に1G(9.8m/s2)がかかります。
また、アシストに関わりなく、高度1000メートルを基準として限界高度ギミック(ゼロ戦が苦手だった成層圏の演出)がかかります。限界高度ギミックが効いてくる高度では急上昇は出来ませんが、上昇出来る高度そのものには制限はありません。ゆっくり旋回しながらゆっくり上昇すれば、どこまでも上昇出来ます。
限界ギミックはコマンドでオンオフ出来ます。邪魔なら「hl」コマンドで切ってください。ある方が(落ちたがりの)私は楽しいですが!
アシスト機能がオンでも(極端な低高度でない限り)機首を上げると急激に減速し、機首を下げると簡単に増速します。
フラップは気分では無く、本当に揚力と空気抵抗が変ります。ベテランのゼロ戦パイロットはフラップを利用して無茶な急旋回をマニューバに組み込んでいました。研究してみてください。
自動フラップオン状態ではある程度まで自動的にフラップを空中でも調整しますが、本来のゼロ戦には自動フラップは搭載されていません。ゼロ戦のベテランパイロットのフラップ操作方法が元になって自動フラップ装置が開発されたため、その効果を簡単に体感するために自動化して実装しています。



****************************************************
~空中戦について~
****************************************************
乗って見れば分かりますが速度増減が非常に強く、横滑りし、場合によっては上下にも滑ります。
そうかと思えば、翼が失っていた揚力を取り戻して空気に乗ると、ものすごい勢いで姿勢を変えたりもします。
一般的なSL戦闘機の挙動から見れば弾を当てにくい摩訶不思議な運動ですが、こちらが当てにくいという事は相手も狙いにくいという事です。
殆どの機体がそもそも出来ない木の葉落としやハイ/ロー・ヨー・ヨーなどは、組み合わせと貴方の腕によっては抜群のマニューバに化けるかもしれません。
また、普通はあまり使われないラダー操作は研究の価値あり。機首をずらして横滑りするので、ちょっと入れるだけでも被弾率が下がります。
スロットルの使い方は独特です。下げても急には減速せず、単に落ちたがります。シャンデルの途中に狙われたら、意図して下げてみましょう。スッと滑って一撃をかわせます。



****************************************************
~着陸について~
****************************************************
基本的にはフライトゲームと同じです。(フライトゲーム程難しくありませんが、綺麗に降りるのはSL飛行機としては少々難しいです)
スロットルを絞ってゆっくり旋回しながら高度を下げ、滑走路延長線上に乗ってください。ラインに乗せるにはラダーよりもエルロン(とそのカウンター)操作の方が調整は楽です。狭い所で高速進入するなら、スロットルを絞ってから機体を90度近くまでロールし、極端な木の葉落としの要領で高度を一気に下げ、滑走路の延長線上で機首を若干上げて速度を殺します。(上げ過ぎに注意!)

高度を十分下げたら滑走路の手前を目指して角度を調整しながら降下してください。着陸アシストが入っていると↓またはSキーを押すと機首上げと同時に自動で推力を上げるので、50%程度の推力まで落として進入角度だけ見ていてもそれなりに進入できます。綺麗に進入するなら70%~60%スロットルがお勧めです。滑走路が正面に見え、ほぼ水平飛行で推力調整だけでやんわり落ちていく状態になれたらクールです。周囲のギャラリーから見ても素晴らしい進入姿勢になっているはずです!

推力を30%以下に落とすと着陸アシストの自動推力調整が切れるので、滑走路の端部に達したら推力をその付近まで下げ、↑↓(WS)で速度と角度を調整しながらやんわりと落ちてください。または、最後にスロットルを30%以下(アシスト切り)にして、機首上げして3点着地しますが、タイミングが速すぎるとすぐ失速してどっすん!です。
逆に進入速度が速すぎると機首上げで浮いてしまいます。そのままどっすんでも着陸は出来ますが、綺麗な3点着陸は貴方の腕前の仕上げの見せ所です!

着艦フック(コマンド「h」で上げ下げ)が降りている時に綺麗に3点着陸姿勢で降りると、ぴしゃりとその場で停止できます。但し、姿勢が整わないとフックは発動しません。
着艦フックが降りていない場合は着陸後もそれなりに滑走します。速やかにスロットルを減らます。スロットルが-5%になるとフラップブレーキも発動し、より素早く減速します。
着陸直後にブレーキ(コマンド「br」)を入れてもスロットルが入っている間は効きません。着艦フックを使うか、スロットルを0%に下げてしまってください。

なめらかな姿勢で着陸した場合はその後タッチアンドゴーも簡単に出来ます(どっすん!すると急減速し再加速になります)ので、腕試しにタッチアンドゴーも遊んでみてください。



****************************************************
~キー操作~
****************************************************
 W/Sもしくは↑/↓...エレベーター操作
 A/Dもしくは←/→...右/左旋回
 シフトキー+A/Dもしくは←/→...ラダー操作(マウスルック時は右/左旋回)
 mでマウスルック
 マウススクロール...ズームイン/アウト(ダイナミックカメラ起動時)
 Eもしくはpage upキー...出力上昇
 Cもしくはpage downキー...出力低下
マウス左クリック...7.7mm機銃(戦闘時デフォルト)または20mm機銃(戦闘時切替中)

****************************************************
~コンボ操作(サポート対象外)~
****************************************************
 ←を連打(0.3秒以内)...ロール左&ラダー左
 →を連打(0.3秒以内)...ロール右&ラダー右
 ←を押し、押しながら→...ロール左&ラダー右
 →を押し、押しながら←...ロール右&ラダー左
 シフトキー+→を押し、押しながらシフトキー+←...ロール左&ラダー右
 シフトキー+←を押し、押しながらシフトキー+→...ロール右&ラダー左



****************************************************
~チャットコマンド~
****************************************************
=========
s
 start/stop
  エンジン起動、停止

=========
br
  車輪ブレーキオン・オフ

=========
af
  自動フラップオン・オフ

=========
la
  着陸アシスト機能オン・オフ

=========
hl
  実用限界高度ギミックオン・オフ

=========
f
  フラップアップ・ダウン(使用すると自動モードオフになります)

=========
ft
  フラップ離陸角度(使用すると自動モードオフになります)

=========
fl
  フラップ着陸角度(使用すると自動モードオフになります)

=========
fbr
  フラップ100%(ブレーキ。使用すると自動モードオフになります)

=========
f␣0~100(␣はスペース)
  フラップ角度マニュアル指定(使用すると自動モードオフになります)

=========
c
  カメラモードチェンジ (通常 -> ダイナミック -> シネマ)

=========
 co
  キャノピー開
 cc
  キャノピー閉

=========
guest
 ゲスト
  ゲストが操縦を許可・禁止

=========
 gear
 ギア
g
  車輪上げ下げ(空中のみ)

=========
 h
 フック
  着艦フック上げ下げ
  下げた状態で綺麗に三点着陸するとその場で停止します。
  停止後はフックを上げるまで移動しません。

=========
 wing
 ウイング
 うぃんぐ
 w(搭乗中のみ。半角のみ)
  主翼格納、展開

=========
load␣[0~](␣はスペースで%を指定)
  積載重量状態変更。100%で全備重量状態

=========
j(搭乗中のみ)
  スタック脱出(上空10Mに移動して停止します)

=========
 mc
  マウスルック時
  マウス方向にエルロンとエレベーター操作が追随します。

=========
 r
  マウスルック時
  マウス方向にラダー操作が追随します。

=========
 menu
 メニュー
  ダイアログメニューの表示

=========
 stick on/off
  アナログスティック有効化・無効化

=========
 vice on/vice off
  VICEのオン/オフ

=========
 bt
  マウスクリック時射撃機銃切替(7.7 or 20mm)

=========
 77
  7.7ミリ機銃選択

=========
 20
  20ミリ機銃選択

=========
 b
  20ミリ機銃一斉射(CMB4発同時射撃。VICEオン時のみ有効)

=========
 tcs on/tcs off
  TCSのオン/オフ

=========
 team X(X=1~4)
  チーム選択、1〜4

=========
 channel
  プライベートチャンネル設定

=========
 channel reset
  プライベートチャンネル初期化

=========
 death message(何か本文)
  死亡メッセージの登録



~ダイアログメニュー~
=========
 Seat
  着席時の姿勢(位置と回転)を変更します。

=========
 Engine
  エンジンの最大推力を変更します。
  栄12型(940馬力・デフォルト)
  瑞星13型(780馬力)
  金星51型(1200馬力)
  着陸アシストが入っているとあまり差は出ません。
  限界高度ギミックが切れていると差は小さいです。

=========
 Load
  代表的な積載状態をワンタッチ選択できます。

=========
 Sensitivity
  マウスルック操縦モード(コマンドmc、r)での、
  3軸の回転操作が発生する感度を調整します。
  マウス方向が指定の角度になった時に回転が最大になります。

=========
 Flap
  f
   コマンドfで下すフラップ角度を指定します

  Decreasing
   フラップが降りている時の回転運動抵抗値の程度を指定します。
   値が大きくなるほど抵抗が増します。

  MaxAutoFlap
   自動フラップオン時
   自動フラップで下されるフラップ最大角度を指定します。

=========
 Wire
  キーボード入力に対する3軸の反応感度を調整します。
  数字が大きいほど旋回開始が速くなります。




****************************************************
~アナログスティック~
****************************************************
下記のURLからファイルをダウンロードして解凍します。ウィルスチェックは必ず自己責任で行ってください。
http://www.tam.ne.jp/~rbk/FlightStick/TeCraftControlStick.zip

インストールの必要はありません。アナログコントローラーをPCに装着し、中身の「TeCraftControlStick.exe」を実行します。
フットペダルは今の所対応していません。
左側の大きな円部分をダブルクリックするとスティック割り付け設定が、Buttonsリストの数字部をダブルクリックするとその番号のボタンへの機能割付けの選択ダイアログが現れます。
右クリックするとメニューが現れます。まず最初に「Property→Set Max」を選んで、装着しているパッド・スティックの入力最大値を記録させます。スティックをぐるぐる回して右上のボックス内の値が全て動かなくなったら、パッドのいずれかのボタンを押すと最大値として設定されます。
軸がずれている様なら、スティックを中立位置にした後「Property→Calibrate」を選ぶと簡易的に中心出しが出来ます。
設定が出来たら一番下の選択ボックスでセカンドライフビューワーを選び、Startボタンを押すと作動開始します。
機体が反応しない時は一旦停止させてから、チャットで「stick on」と入力して再度開始します。
いずれかの押しやすいボタンに「PauseSendStickData」を割り付けておくことをお勧めします。コントローラーのボタンでデーター送信を中断・再開できます。(中断しないとチャットが出来ませんので!)
また、ボタン操作で「Engine」を割り付けておくのも便利です。自動的にスティックオン指令を出した後、エンジンをスタートしてくれます。
「Property→Save」で名称を決めて保存すると、その名前で設定状態が保存され、次回起動時に右クリックメニューの中に追加されます。サンプルに普通のジョイパッドとフライトスティックコントローラーの軸設定を入れてあります。ボタン割り付けは殆どしていないので、お好みで設定してください。
「Save to Default」で保存すると、起動時デフォルトの状態として保存されます。
その他の詳細はZIPに同封の説明を参照してください。



****************************************************
~実機について~
****************************************************
正式採用時の形式は零式艦上戦闘機11型(A6M2a)。11型は着艦フックや翼の折りたたみ機構を持たない機体タイプで、名前に似合わず空母に降りられません。(試作機が急遽採用された為)
ですので、本格的な空母艦載機としての正式化は本機21型が最初のタイプとなります。

真珠湾攻撃~ミッドウェイ海戦当時の赤城航空隊(第一航空艦隊旗艦/一航戦旗艦)所属機のカラーリングが、同封の白色の機体のカラーです。胴体の赤線は隊長マークでは無く空母赤城所属を表します。他に尾翼には機体番号が、また、その上下に階級によって線が入りますので、お好みで書き込んでください。

緑のタイプは、この機体の造形の元となった中島飛行機工場がライセンス製造した物に塗られていた塗装の代表例です。主翼先端の識別塗装の黄色はあったりなかったりします。プロペラの茶色は本来後期型零戦の色なのですが、部品を使いまわしていた物か、一部の部隊では21型でもこの色の物があったようです。基本的には21型のプロペラやスピナーは時代や製造によらず銀色なので、お好みで差し替えてください。日の丸の白縁はあったりなかったりします。日の丸が見えにくいので強調する為の塗装ですが、戦争終盤に近付くとない物が多いように思います。目立つ事を嫌ったのかもしれません。

落下タンクは毎回原則新品なので、いずれの基本機体もあえて汚しを入れていません。緑の方が若干塗装の禿げが激しいのは、この色の当時の戦局や使用されていた場所を良く表現しています。空母艦載機は塗装が剥げるとすぐ錆びてしまうので割と頻繁に塗り替えを行っていたそうですが、機体が濃緑色に塗られる頃には陸上基地からの発進が主である上、物資不足もあって終戦に近い映像になるほどハゲハゲになっていきます。

ファットパックの、あめ色で胴体に青いV字は「大空のサムライ」著者・坂井三郎機。日本で最も有名なエースパイロットでしょう。
同じくファットパックの緑で撃墜マークが勇壮重厚な機体はラバウルのエース岩本徹三機です。撃墜マークは伊達ではありません。
緑で背面が薄橙色の機体は練習機塗装です。大分航空基地で使用されていた、恐らく特攻隊の練習機の塗装です。日本の練習機は一般的にこのように橙色の塗装がどこかに取り入れられていたようです。実機を使った練習を行っていた物と思われ、大分だけでなく他の部隊でも単座の正式機にこれに類する塗装を施した資料が残っています(練習用の零戦は二人乗りで武装も脆弱です。)。
痛機には実機はありません(当たり前!)が、素晴らしく痛い塗装に仕上がっています。


三菱が設計を担当。96式艦上戦闘機(「風立ちぬ」のあれ)の後継機として開発され、海軍の荒唐無稽!な要求に応えるべく、一層の洗練が施された進化型と言えます。
模擬戦闘の条件下では96戦にはっきりと劣っていた様で、後のエースパイロット坂井三郎でさえ96戦には負け続けだったそうです。※1

が・・・、
一旦実戦となると、その強さは最早伝説といっていいでしょう。連合軍にも「ゼロ」とそのまま※2呼ばれ、有名な

ゼロと低空で格闘するな、
ゼロとは単騎で戦うな、
逃げるゼロを追うな

が言い渡されるなど、非常に警戒されました。


防弾装備や防御が無いのが弱点と揶揄されますがそれは戦争終盤の非熟練パイロットの話で、「当たらなければどうという事は無い」と坂井氏も豪語するほどだった為、経験を積んだ現場パイロットにはあまり問題視されていなかった様です。

脱出方法が無いという説はデマで、実際にはパラシュートを装着するのが既定でしたが、現場搭乗員は殆ど誰もそれを装着せず、ベルトを装着せず単に座布団代わりにしていたとの事。潔い士魂という事なのか・・・という逸話ですが、その後の歴史を知っている我々としては、有為なベテランパイロット達には生還する努力をして頂きたかったという感想です。当時の風潮は我々の常識とは異なるという事なのでしょう・・

機首に7.7ミリ機関銃を2丁(コクピット内正面にある二つの箱がそのお尻です)と、翼内に20ミリ機関銃を左右1丁づつ装備し、ひらひらと舞いながら7.7ミリ機銃で追いつめて、20ミリでトドメがベテランの常套だったようです。

また、燃料満載で2,200キロ、胴体下に追加タンク搭載で3,350キロという長大な航続距離を誇り、この長い足は日本海軍の作戦に大きく影響を与えています。
爆撃計画が有利に広がったのは有名ですが、資源もない孤島を占領して歩いていた理由の一つがこの航続距離にあります。島を不沈空母に見立て飛行場を作り、飛行隊が長躯移動して敵に当たるという構想をしていました。(しかし、ガタルカナル島はやりすぎだ!)

3,000キロ以上を飛行する半日近い飛行時間中気になるトイレは、小さい方は備え付けの袋の中にして窓から捨てていたそうですが、失敗すると顔中にぶちまけてしまったとの事。大きい方は飛行服の中でするしか無く、また、慣れない初陣のパイロットなどは空戦の緊張で粗相をしてしまう事もあったようで、これらの後始末を何も言わずに黙ってピカピカにするのは基地の下っ端の大事な任務だったとの事。

映画「永遠のゼロ」に描かれている通り、ミッドウェイやガ島争奪戦の前後から次第に損害が目立ち始め、熟練パイロットを失っていった日本軍は劣勢に立たされていきます。
以後、熟練パイロットの穴埋めをすべく、新型の米軍機に対応すべく、様々な派生型が試作・生産されていきますが、エンジン出力が追いつかずあまり成功したタイプは出ていません。

「永遠のゼロ」では乗り降りに翼の上を無造作に歩き回っていますが、本当は本機搭乗アニメの様に、胴体に付いている足かけの上をカニ歩きで搭乗します。翼付け根の四角形の赤枠部分がフラップになっていて大変に脆くなっており、あんな風にドタバタ歩き回ると踏み抜いて壊してしまいます。

着陸用のタイヤは本機でも左・右の順に収納しますが、実は設計上は左右同時に収容する構造になっていて、単に油圧が足りない為にバラバラに動く事になってしまったようです。この為、当時の実写でも機体ごとに車輪格納の動きがよく見ると多少違う事があります。運よく当たりくじを引くと、左右同時に動くゼロ戦もあったかもしれません。


ダイアログ選択できるエンジンは、いずれも21型にちなんだものです。

栄12型エンジンが史実の搭載エンジン。小型軽量の傑作エンジンです。複列星形14気筒、940馬力、中島飛行機。
陸軍の名機「隼」にも採用されるなど、大戦初期の日本の空を支えた代表的なエンジンです。シミュレートはしていませんが、実機では温度変化にはかなりデリケートだったようで、温度メーターを見ながらカウルフラップを開閉し、高度によっても細かく微調整していたそうです。
点火プラグが手を突っ込める位置になく、専用の工具で取り外し、取り付けるそうですが、この作業が非常に大変だったらしくフライトの度にやらされる取り外しと放電部の磨き作業が苦労話として残っています。(「もったいない」という理由で。本来は点火プラグは毎回取り替えて捨ててしまうのが正解。この為、パイロット思いの良心的なベテラン整備員は、真夜中に上官に秘密でこっそり新品と取り替えていたとかいないとか。。)
また、オイルパッキンが当時の日本では上手く作れず、熟練の整備兵はカウルや胴体のオイル漏れの汚れ跡も見ながらエンジンの調子を判断したそうです。中島飛行機製造の機体(本機)ではオイル漏れが特にひどい物が混じっていたそうで(エンジン製造メーカーなのに何故?)、パイロットには三菱工場製が好まれたという逸話も残っています。
なお、現在米国に残っている飛べるゼロ戦でも、このオイル漏れは健在。室内展示中には下にパットを置いて床を汚さない様にしています。

瑞星13型エンジンは試作1号2号機に搭載されていたエンジンで、こちらは機体設計と同じ三菱製、複列星形14気筒、780馬力。
試作当時は栄に比べて出力が小さく、また、海軍側からの指示(命令?)もあって不採用となっていますが、当時既に技術的には安定、つまり「枯れ」つつあった栄エンジンより改良の余幅は大きかったかもしれません。設計チームは「今度こそは自社エンジンで!」と意気込んでいた所の変更指示で、大変がっかりされたとの事。がっかりを拾って選択肢に含めました。

金星5x型エンジンは設計当初に検討されましたが、直径が大きく前方視界を塞ぐことから、パイロットの意見に気を使って採用されませんでした。
設計チーム主席の堀越技師が後年、初めから金星を選ばなかったことを大変悔やんだそうで、”歴史にIF”のエンジン選択肢です。
1200馬力は金星51型のスペックで、年代的に(採用していたなら)50型のいずれかが搭載されただろうと思われます。後期型零戦の一部では金星が採用されている物もありますが、本来の21型のカウルには大きすぎて収まりません。


※1
模擬戦闘は同じ高度でヨーイ、ドン!でスタートして、SLの空中戦の様に限られた狭い範囲でクルクル回りながら模擬戦闘します。この為、ゼロ戦より運動性が高い96式の方が圧倒的に強かったそうです。
もっとも、その96式も正式化当初は複葉の95式艦上戦闘機に同じようにやられっぱなしだったそうで、時代を追うごとに少しづつ、運動性よりも行動半径や速度に重点が移って行った歴史を垣間見ることが出来ます。
当の坂井三郎氏の見解では、空戦性能もさることながら何よりゼロ戦がありがたかったのは、どんなに飛んでも燃料切れの心配が無かった、だそうです。この為、坂井氏は運動性が向上した32型(でも航続距離は落ちた)を非常に批判しています。他のパイロットの間でも32型は不評が多かったようで、戦争が始まる前の議論と実戦経験後との思想の変化も垣間見える逸話です。

※2
連合軍がつけたコードネームはZEKE(ジーク)ですが、現代でも「ゼロ」という方が通じます。
また、「ぜろせん」なのか「れいせん」なのかにコダワリを持つ人が時々おられますが、調べてみると実は両方使われていました。よって、ゼロ戦でも零戦でも正解です。



****************************************************
... Studio K-LYSMER ...
****************************************************
3D Model and chief designer : syunki Igaly (A,a,b)
Script : rbk drachnyd
Texture : syunki Igaly & Estacio Squall (default), keke55 resident & yk tachikawa (fatpack)
Beta Test : Estacio Squall, keke55 resident, yk tachikawa , mukuta Proto
Special Thanx to : tetugame yoshikawa, Akira Souther, Cubey Terra, Creem Pie and all aviators in Second Life!
  


Posted by RBK Drachnyd(しお) at 18:15Comments(0)飛行機
2015年12月14日

飛行機エンジン出来ました

Teクラフトのてっちゃんに無理を言ってエンジン試作をやらせて頂いてから苦節二年。。ようやくにしてそれなりに満足のいく仕上がりの飛行機用エンジンが出来上がりました。
その名も「ACMS-Ptero」。




翼が風を捕まえ、翼が風に乗ることをコンセプトにしているという点では飛行機を本格的に始める前から引きずっているコンセプトですが、これが意外とSLでは難しい。。ある程度納得するのにまるまる2年かかりました。ハリボテエレジー以上に自分で満足できるスクリプトは金輪際ないだろうと思ってましたが、やってみるものでついに来た感じです。



初回実装はなんとあの零式艦上戦闘機(ゼロ戦)です。新ブランド「K-LYSMER」さんが採用してくれました。




最近某所が発売のとお題がかぶってますが、向こうは三菱製、こちらは(液漏れがおちゃめな)中島飛行機のライセンス生産機体が造形の元になっています。見比べてみると微妙な違いが再現されています。というか、造形化のsyunki lgalyさんが周囲の「ゼロ戦だからしょうがないよねー」の言葉の元に出される情け容赦無いダメ出しに泣きながら対応していたのは半年前の事です。。(笑 お疲れ様でした。

買ってくださいと書くと商用利用になるので書きませんが、誰でも遊べるREZZERの設置予定場所は確保しましたので近日中に流します。是非のって遊んでみてください。今までにない動きをします。(何しろ私が宮崎アニメを理想像にしてますから、既存メーカーの一般常識なんて無視です。でも空戦も結構強いですよ!(笑))  


Posted by RBK Drachnyd(しお) at 23:00Comments(0)飛行機
2015年11月19日

SL航空機アナログ化①

昔キー連打方式で試作してあまり面白くなかったので放置していたアナログスティックによる乗り物操縦装置を試作しました。
↓なんだかこんな感じです。↓


動画右上のウィンドウが入力用ソフト(Windows)で、原理はJoy2Keyとほぼ同じ。
一番下の選択肢で選んだウィンドウが最前面にある時に入力内容をチャットの3チャンネルまたは0チャンネルで送信してきます。送信フォーマットは単純で、rotationのx,y,z,s軸が各々エルロン、エレベーター、ラダー、スロットルの値になっているだけです。
左側の赤い円部分がアナログデーターの表示部で、赤い小さな円が左右(エルロン)、上下(エレベーター)、画面回転がラダー、円の色がスロットルの値を示します。この部分をダブルクリックすると軸割り当ての設定画面が開きます。

数字の1~32の部分がボタンへの機能割り当てで、エンジン、カメラ、銃などの機能やチャットコマンドを指定できます。ダブルクリックすると選択ダイアログが出るようになっています。
他に右クリックメニューで設定の保存や保存済み設定の選択が出来ます。



取りあえず試作中の飛行機用。興味のある方はどうぞ。対応している飛行機がまだ制作中で、購入できる機体が一機もないので、実際に操縦してみたい場合はRBK DrachnydまでIMを下さい。
ダウンロードされる際はウィルスチェックを必ずしてください。チェックしておりません。
サンプルにフライトスティックの軸設定とジョイパッドの軸設定を入れてあります。
http://www.tam.ne.jp/~rbk/FlightStick/TeCraftControlStick.zip
  
タグ :lsl


Posted by RBK Drachnyd(しお) at 19:33Comments(0)飛行機
2015年11月17日

LSLエディター勝手に改造版⑤



http://www.tam.ne.jp/rbk/lslEditor/LSLEditor.exe
(↓落とせない場合はコチラ。中身は一緒です)
http://www.tam.ne.jp/rbk/lslEditor/LSLEditor.zip

ウィルスチェックは自己責任でお願いいたします。チェックしておりません。
圧縮ファイルやインストーラーではなく、そのまま実行ファイルですので、既存のフォルダ内の同じファイルを上書きしてください。
バージョン数字勝手に修正しています。(本家更新がかかった場合にバージョン番号が変わりますので、自動アップデート機能は一応ONのままを推奨いたします。どうにも望み薄の気配ですが・・)
デバッグ機能(F5キー)は意味がないのと対応させていませんのでキーショートカットもメニューも殺してあります。構文チェック(F6キー)は実装させています。

以下の定数を追加しました。
PSYS_PART_RIBBON_MASK
PSYS_PART_START_GLOW
PSYS_PART_END_GLOW
PSYS_PART_BLEND_FUNC_SOURCE
PSYS_PART_BLEND_FUNC_DEST
PSYS_PART_BF_ONE
PSYS_PART_BF_ZERO
PSYS_PART_BF_DEST_COLOR
PSYS_PART_BF_SOURCE_COLOR
PSYS_PART_BF_ONE_MINUS_DEST_COLOR
PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR
PSYS_PART_BF_SOURCE_ALPHA
PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA


本家公開版はこちら。
http://www.lsleditor.org/

ソース取得元はこちら。
http://sourceforge.net/projects/lsleditor/files/Source/


LSLEditorはGPL2ライセンスです。
改変後ソースが何が何でも必要な方はIM等でご一報ください。いらないと思いますが。。w
  


Posted by RBK Drachnyd(しお) at 16:26Comments(0)雑記
2015年10月19日

LSLエディター勝手に改造版④



http://www.tam.ne.jp/rbk/lslEditor/LSLEditor.exe
(↓落とせない場合はコチラ。中身は一緒です)
http://www.tam.ne.jp/rbk/lslEditor/LSLEditor.zip

ウィルスチェックは自己責任でお願いいたします。チェックしておりません。
圧縮ファイルやインストーラーではなく、そのまま実行ファイルですので、既存のフォルダ内の同じファイルを上書きしてください。
バージョン数字勝手に修正しています。(本家更新がかかった場合にバージョン番号が変わりますので、自動アップデート機能は一応ONのままを推奨いたします。どうにも望み薄の気配ですが・・)
デバッグ機能(F5キー)は意味がないのと対応させていませんのでキーショートカットもメニューも殺してあります。構文チェック(F6キー)は実装させています。



新規追加の関数・定数は調べておらず今回はありませんが、ユーザー定義関数も入力補間で拾うようにしました。
また、補間対象のスコープ認識が元々のが甘かったのを修正しました。スコープ内しか拾わなくなっているはずです。
一文字の変数名のに入力補間がいちいち出るのも邪魔なので、1文字の物は補間候補にならない様にしました。



本家公開版はこちら。
http://www.lsleditor.org/

ソース取得元はこちら。
http://sourceforge.net/projects/lsleditor/files/Source/


LSLEditorはGPL2ライセンスです。
改変後ソースが何が何でも必要な方はIM等でご一報ください。いらないと思いますが。。w
  
タグ :LSL


Posted by RBK Drachnyd(しお) at 21:24Comments(0)雑記
2015年05月26日

LSL:文字が全角かを調べる

既出かもしれませんが・・
フローティングテキストを左寄せ・右寄せにしたいことがあって、文字が半角か全角かを調べる小物をつくりました。(作ったというほどでもありませんが・・(笑))

URLエンコードでは半角文字は%アスキー番号、または元の文字のままとなり、全角文字は文字番号を1バイトづつにきって%nn%mm%iiのようになります。よって、全角文字かどうかはllEscapeURL()の戻り文字列の長さが3以下かどうかを見ればよい、という事になります。



//引数に1文字を与えると全角文字の場合にTRUEを返します。
integer isMultiByteChar(string _char)
{
return (llStringLength(llEscapeURL(_char))>3);
}
  
タグ :LSL


Posted by RBK Drachnyd(しお) at 15:49Comments(0)小物
2014年09月04日

公式ビューワー行数制限解除

公式ビューワーのLSLエディットダイアログがようやくにして行数制限解除みたいですね。。4000行をカットアンドペーストで生成してみましたが問題なく受け入れる様です。。。T_T

酷い苦労を今までしておりましたが、ようやく。。ようやくにして自由の身に。。;_;/
  


Posted by RBK Drachnyd(しお) at 15:50Comments(0)雑記
2014年08月16日

LSLエディター勝手に改造版③



http://www.tam.ne.jp/rbk/lslEditor/LSLEditor.exe

ウィルスチェックは自己責任でお願いいたします。チェックしておりません。
圧縮ファイルやインストーラーではなく、そのまま実行ファイルですので、既存のフォルダ内の同じファイルを上書きしてください。
バージョン数字勝手に修正しています。(本家更新がかかった場合にバージョン番号が変わりますので、自動アップデート機能は一応ONのままを推奨いたします。どうにも望み薄の気配ですが・・)
デバッグ機能(F5キー)は意味がないのと対応させていませんのでキーショートカットもメニューも殺してあります。構文チェック(F6キー)は実装させています。


以下の、最近追加された関数、定数類を追加しました。
PRIM_LINK_TARGETが強力です。llSetLinkPrimitiveParams系の命令で、一発で複数の子プリムに命令を放り込めるようになるようです。

PRIM_LINK_TARGET
PRIM_NORMAL
PRIM_SPECULAR
PRIM_ALPHA_MODE
PRIM_ALPHA_MODE_NONE
PRIM_ALPHA_MODE_BLEND
PRIM_ALPHA_MODE_MASK
PRIM_ALPHA_MODE_EMISSIVE
PRIM_TYPE_LEGACY
CHARACTER_DESIRED_SPEED
CHARACTER_RADIUS
CHARACTER_LENGTH
CHARACTER_ORIENTATION
VERTICAL
HORIZONTAL
TRAVERSAL_TYPE
TRAVERSAL_TYPE_FAST
TRAVERSAL_TYPE_SLOW
TRAVERSAL_TYPE_NONE
CHARACTER_TYPE
CHARACTER_TYPE_A
CHARACTER_TYPE_B
CHARACTER_TYPE_C
CHARACTER_TYPE_D
CHARACTER_TYPE_NONE
CHARACTER_AVOIDANCE_MODE
AVOID_CHARACTERS
AVOID_DYNAMIC_OBSTACLES
AVOID_NONE
CHARACTER_MAX_ACCEL
CHARACTER_MAX_DECEL
CHARACTER_DESIRED_TURN_SPEED
CHARACTER_MAX_TURN_RADIUS
CHARACTER_MAX_SPEED
CHARACTER_ACCOUNT_FOR_SKIPPED_FRAMES
CHARACTER_STAY_WITHIN_PARCEL
CHARACTER_CMD_JUMP
CHARACTER_CMD_SMOOTH_STOP
CHARACTER_CMD_STOP
AGENT_LIST_PARCEL
AGENT_LIST_PARCEL_OWNER
AGENT_LIST_REGION
GCNP_RADIUS
GCNP_STATIC
SIM_STAT_PCT_CHARS_STEPPED
PU_SLOWDOWN_DISTANCE_REACHED
PU_GOAL_REACHED
PU_FAILURE_INVALID_START
PU_FAILURE_INVALID_GOAL
PU_FAILURE_UNREACHABLE
PU_FAILURE_TARGET_GONE
PU_FAILURE_NO_VALID_DESTINATION
PU_EVADE_HIDDEN
PU_EVADE_SPOTTED
PU_FAILURE_NO_NAVMESH
PU_FAILURE_DYNAMIC_PATHFINDING_DISABLED
PU_FAILURE_PARCEL_UNREACHABLE
PU_FAILURE_OTHER
JSON_INVALID
JSON_OBJECT
JSON_ARRAY
JSON_NUMBER
JSON_STRING
JSON_NULL
JSON_TRUE
JSON_FALSE
JSON_DELETE
FORCE_DIRECT_PATH
PATROL_PAUSE_AT_WAYPOINTS
PURSUIT_OFFSET
REQUIRE_LINE_OF_SIGHT
PURSUIT_FUZZ_FACTOR
PURSUIT_INTERCEPT
PURSUIT_GOAL_TOLERANCE
ERR_GENERIC
ERR_PARCEL_PERMISSIONS
ERR_MALFORMED_PARAMS
ERR_RUNTIME_PERMISSIONS
ERR_THROTTLED
PERMISSION_RETURN_OBJECTS
PERMISSION_TELEPORT
PERMISSION_SILENT_ESTATE_MANAGEMENT
PERMISSION_OVERRIDE_ANIMATIONS
OBJECT_RETURN_PARCEL
OBJECT_RETURN_PARCEL_OWNER
OBJECT_RETURN_REGION
WANDER_PAUSE_AT_WAYPOINTS

llAttachToAvatarTemp
llCreateCharacter
llDeleteCharacter
llEvade
llExecCharacterCmd
llFleeFrom
llGenerateKey
llGetAgentList
llGetAnimationOverride
llGetClosestNavPoint
llGetMaxScaleFactor
llGetMinScaleFactor
llGetPhysicsMaterial
llGetSimStats
llGetStaticPath
llJson2List
llJsonGetValue
llJsonSetValue
llJsonValueType
llList2Json
llNavigateTo
llPatrolPoints
llPursue
llResetAnimationOverride
llReturnObjectsByID
llReturnObjectsByOwner
llScaleByFactor
llSetAnimationOverride
llTeleportAgent
llUpdateCharacter
llWanderWithin
llXorBase64




本家公開版はこちら。
http://www.lsleditor.org/

ソース取得元はこちら。
http://sourceforge.net/projects/lsleditor/files/Source/


LSLEditorはGPL2ライセンスです。
改変後ソースが何が何でも必要な方はIM等でご一報ください。いらないと思いますが。。w
  


Posted by RBK Drachnyd(しお) at 12:14Comments(2)雑記
2014年03月01日

斜面に沿って回転させる

知人から質問を受けたので久しぶりに。。

下のSSの様に、ある特定の方向(黄色いUFOの方向)を向いているプリムを、











と言う風に斜面に沿って元向いていた方向を維持しながら傾斜させることを考えます。

これは、以前にだらだらと書いておりました、
http://rbk.slmame.com/e971594.html
の変種で、戦車の車体が傾斜している地面、回転させたいプリムが砲塔、そして砲身が無いバージョンになります。

このような場合は、まず、llCastRay()を使って、下の地面の法線ベクトルと、黄色のUFOの方向(つまりllRot2Fwd(llGetRot())を取得します。
法線ベクトルとは、面に垂直な方向を向いている長さ1のvectorの事です。つまり、回転対象の上の面がこのベクトルの方向を向けば良いという事になります。つまり下の図のように回転させればよいという事で、この場合は元々の自分の上方向のベクトルllRot2Up(llGetRot())と、法線ベクトルの間でllRotBetween()を取ってやると回転角の差分が求まります。今の自分の回転にこの回転差分をかけてやると、上面方向は一致します。





上面の傾きが一致しました。ただ、この回転だけを仮に実際にやると、llRot2Up()で上面だけ特定方向を向けたときのように、正面がどこを向くかが不定になります。
そこで、次に、下のSSの様に、その面内で回転して元見ていた黄色のUFOの方向を向けさせます。






この時に少し考え方に工夫を入れてやると、この問題は簡単になります。まず、下の図のように、先に回転させた白線の回転結果と反対に、自分の回転が完全にゼロになるまで、UFOと自分の回転を戻してやります。





具体的には、先に取得しておいた自分の元々の正面方向(UFOの方向)のベクトルを、白線矢印の回転をした後の自分の回転で割ります。
自分の方は、自分の回転を自分の回転で割るので常にZERO_ROTATIONになりますので、<1,0,0>と、<UFOベクトルのX,UFOベクトルのY,0>との間のllRotBetween()を取れば、すぐに平面上での回転方向は定まります。

つまり、手順的には、

1)
自分の正面方向の単位ベクトルllRot2Fwd(llGetRot)を求めておき、

2)
llCastRay()の結果と自分の上方向のノルムllRot2Up(llGetRot)の間の回転角を求め、これを現在の自分の回転にかけた値を先に求め、

3)
1)の正面方向ベクトルを2)の結果の回転で割って回転後のローカル座標系での見かけの方向に直し、次にその結果の上下方向回転だけをゼロにした、つまりZ値だけ0にしたベクトルのノルムを求め、

4)
3)の結果とローカル座標系の正面方向<1,0,0>とのllRotBetweenを取り、

5)
4)の結果に2)の結果をかけたrotationをllSetRot()等する


という手順になります。
この場合は、2)の手順の時にまず一つのベクトルを求め、3)の手順でもう一つのベクトルを求め、これが直交ベクトルになるので4)と2)の合成(5)で3次元回転が一意に決まる、という手順です。また、5)の掛け算の順は、必ず4)に2)をかけなければなりません。これは、4)がローカル回転、2)がグローバル回転になるからです。

他の手順もありますが、3次元回転をベクトルで割り出す場合は基本的に2手順で2つの直交するベクトルを求めて、もう1次元分の向きが自動的に定まるように計算します。
  


Posted by RBK Drachnyd(しお) at 19:48Comments(0)算数
2014年02月21日

ところてんの歌(完成版)

ところてんの歌を、Cannaregio Franizzi様が完成させてくださいました。パキプシュ(;_;/

動画化しましたのでどうぞご賞味ください。

♪となりのとっころ とっこ~ろ とっころ とっこ~~ろ
♪バグの山に むかしから住んでる~(T_T/~


  


Posted by RBK Drachnyd(しお) at 19:57Comments(0)雑記
2012年02月16日

LSLエディター勝手に改造版②



http://www.tam.ne.jp/rbk/lslEditor/LSLEditor.exe

最近追加された関数、定数類を追加しました。

ウィルスチェックは自己責任でお願いいたします。チェックしておりません。
圧縮ファイルやインストーラーではなく、そのまま実行ファイルですので、既存のフォルダ内の同じファイルを上書きしてください。
バージョン数字勝手に修正しています。(本家更新がかかった場合にバージョン番号が変わりますので、自動アップデート機能は一応ONのままを推奨いたします。どうにも望み薄の気配ですが・・)
デバッグ機能(F5キー)は意味がないのと対応させていませんのでキーショートカットもメニューも殺してあります。構文チェック(F6キー)は実装させています。


本家公開版はこちら。
http://www.lsleditor.org/

ソース取得元はこちら。
http://sourceforge.net/projects/lsleditor/files/Source/


LSLEditorはGPL2ライセンスです。
改変後ソースが何が何でも必要な方はIM等でご一報ください。いらないと思いますが。。w


20120217追記
さっそく不足定数を発見して追加。
なお、ソース配布元のsourceforgeの方で、CE版という名前で新しい関数類が追加された英語版のバイナリがアップされていました。プロジェクトが消えてしまう症状が無いなら、そちらの方が良いかと思います。  


Posted by RBK Drachnyd(しお) at 23:44Comments(0)小物
2012年02月16日

なびするの後継はこれ?

まだ名称も決まっていないそうですが、多分これですね。

セカンドライフのSNS(β) :※名称仮
http://sl-sns.com/

すりんくの作者のSon ClaveさんがOpenPNEをベースに改良して運営テスト中とのことですが、既にアバターの確認によるなりすまし防止機能や、すりんくとの連携も実装されていて、デフォルトとは一味違います。流石ですね。要改造とおっしゃっておられましたので、まだまだ発展しそうです。
  


Posted by RBK Drachnyd(しお) at 17:30Comments(0)雑記
2011年11月09日

llSetKeyframedMotion()だそうです。

QAvimatorの様にキーフレームの姿勢を指定してやると自動補間してなめらか再生してくれる非物理用の関数の様です。テスト実装とのこと。
これは便利そうですね。。。-_-+
お正月ごろには遊べるでしょうか。。。

http://wiki.secondlife.com/wiki/LlSetKeyframedMotion
  


Posted by RBK Drachnyd(しお) at 21:57Comments(2)雑記