はじめに

llSetTextureAnim はテクスチャを常にアニメーションさせるために必要な関数です。この中のモード SMOOTH は、 そんなに解説が書いていないので、なんとなくサンプルを丸コピーして、適当にいじって動かしているという方も多いと思います。そこで今回は、この llSetTextureAnim の SMOOTH のみに焦点をしぼって使い方を調べました。

llSetTextureAnim の SMOOTH のみの解説

テストに使用するテクスチャを用意しました。
TestTexture

key	texture	=	"647d14d9-b739-903e-1bb3-fa2450b9c191";

パブリックドメインとします。これ以外にも自由に使っていただいてかまいません。

まず、llSetTextureAnim を使用するに当たって、引数が7つあります。解説は wiki から引用します。

integer	mode		モードフラグのマスク
integer	face		面 番号もしくは ALL_SIDES
integer	sizex		横フレーム ( ROTATE とSCALE では無視される)
integer	sizey		縦フレーム ( ROTATE とSCALE では無視される)
float	start			開始位置/フレーム番号 ( ROTATE ではラジアン)
float	length		表示するフレーム数 ( ROTATE ではラジアン)
float	rate			毎秒のフレーム数(0 にすべきではありません)

ここで、SMOOTH は mode に入れる必要があるのですが、SMOOTH を設定する場合は、さらに LOOP を入れないと実は動きません。

start() {
	key		texture	=	"647d14d9-b739-903e-1bb3-fa2450b9c191";
	integer	mode	=	ANIM_ON | SMOOTH;
	integer	face	=	ALL_SIDES;
	integer	sizex	=	0;
	integer	sizey	=	0;
	float	start	=	0.0;
	float	length	=	0.0;
	float	rate	=	1.0;
	llSetTextureAnim(0, face, 0, 0, 0.0, 0.0, 0.0);
	llSetTexture(texture, face);
	llSetTextureAnim(mode, face, sizex, sizey, start, length, rate);
}
default{state_entry(){start();}}

↑上記のスクリプトを起動してみてください。テクスチャが1ループも動かないはずです。なお、今回テクスチャの設定を初期化するために、 llSetTexture も使用しています。

start() {
	key		texture	=	"647d14d9-b739-903e-1bb3-fa2450b9c191";
	integer	mode	=	ANIM_ON | SMOOTH | LOOP;
	integer	face	=	ALL_SIDES;
	integer	sizex	=	0;
	integer	sizey	=	0;
	float	start	=	0.0;
	float	length	=	0.0;
	float	rate	=	1.0;
	llSetTextureAnim(0, face, 0, 0, 0.0, 0.0, 0.0);
	llSetTexture(texture, face);
	llSetTextureAnim(mode, face, sizex, sizey, start, length, rate);
}
default{state_entry(){start();}}

↑ LOOP を入れると動き始めましたよね。つまり、LOOP は必須です。ちなみに1秒で右端まで行って、最初に戻るというスクリプトです。

動く方向の話ですが、SMOOTH に設定して動く方向はU軸の + ということです。反対に動かしたければ、 REVERSE を mode に追加すればU軸の - へ動きます。PING_PONG を設定すれば、テクスチャが一巡時に、逆方向へ動きが変わるということです。もし 90 度の方向へ動かしたいという場合は、llRotateTexture で設定する必要があります。(llSetTextureRot はないので注意)

sizex、sizey のパラメータについて、必要ないのでは思う方がいるかもしれません。SMOOTH 以外の場合、つまりテクスチャをパラパラ漫画のようにコマ送りで、再生するときに使用するパラメータとして考えると、SMOOTH では有効ではないパラメータのようにみえます。しかし、 SMOOTH の場合でも実は有効な引数となっています。

start() {
	key		texture	=	"647d14d9-b739-903e-1bb3-fa2450b9c191";
	integer	mode	=	ANIM_ON | SMOOTH | LOOP;
	integer	face	=	ALL_SIDES;
	integer	sizex	=	2;
	integer	sizey	=	2;
	float	start	=	0.0;
	float	length	=	1.0;
	float	rate	=	1.0;
	llSetTextureAnim(0, face, 0, 0, 0.0, 0.0, 0.0);
	llSetTexture(texture, face);
	llSetTextureAnim(mode, face, sizex, sizey, start, length, rate);
}
default{state_entry(){start();}}

↑を実行すると分かるとおり、1枚のテクスチャの左上の部分のみ使用されます。
つまり、1枚のテクスチャを横に2等分、縦に2等分した後の左上のテクスチャが、全体のテクスチャの座標として考えます。0 に指定した場合は、デフォルトで 1 が入るようです。これまで 0 としていたのですが、1 とした方が読みやすいかもしれません。普通はテクスチャ1枚使うほうが多いと思うので、このパラメータの使い道はないと思います。

length のパラメータも必要ないのではと思う方もいるかもしれません。実はそんなことありません。 length を今回 0.0 に設定してましたが、この場合は、デフォルトの 1.0 が使用されているのです。では、 length は何に影響するのか。

start() {
	key		texture	=	"647d14d9-b739-903e-1bb3-fa2450b9c191";
	integer	mode	=	ANIM_ON | SMOOTH | LOOP;
	integer	face	=	ALL_SIDES;
	integer	sizex	=	0;
	integer	sizey	=	0;
	float	start	=	0.0;
	float	length	=	0.5;
	float	rate	=	1.0;
	llSetTextureAnim(0, face, 0, 0, 0.0, 0.0, 0.0);
	llSetTexture(texture, face);
	llSetTextureAnim(mode, face, sizex, sizey, start, length, rate);
}
default{state_entry(){start();}}

↑今回、lengthを 0.0 (デフォルトの 1.0 )から、 0.5 へ変更しました。
実行すると分かるように、テクスチャのU座標0.5で、元に戻っています。つまり、lengthは、テクスチャモーションのループポイントということになります。

さて、これまでで、テクスチャを動かす方法と、動かす方向、動かしたときの最大値(ループポイント)を設定する方法が分かりました。

次は、テクスチャを動かす速度です。速度には、 rate を使用します。次のサンプルのように、 1.0 と設定したします。

start() {
	key		texture	=	"647d14d9-b739-903e-1bb3-fa2450b9c191";
	integer	mode	=	ANIM_ON | SMOOTH | LOOP;
	integer	face	=	ALL_SIDES;
	integer	sizex	=	1;
	integer	sizey	=	1;
	float	start	=	0.0;
	float	length	=	1.0;
	float	rate	=	1.0;
	llSetTextureAnim(0, face, 0, 0, 0.0, 0.0, 0.0);
	llSetTexture(texture, face);
	llSetTextureAnim(mode, face, sizex, sizey, start, length, rate);
}
default{state_entry(){start();}}

↑を実行すると分かるとおり、rate を 1.0 とすると 1.0 秒で、U座標が 1.0 までいきます。

start() {
	key		texture	=	"647d14d9-b739-903e-1bb3-fa2450b9c191";
	integer	mode	=	ANIM_ON | SMOOTH | LOOP;
	integer	face	=	ALL_SIDES;
	integer	sizex	=	1;
	integer	sizey	=	1;
	float	start	=	0.0;
	float	length	=	1.5;
	float	rate	=	1.0;
	llSetTextureAnim(0, face, 0, 0, 0.0, 0.0, 0.0);
	llSetTexture(texture, face);
	llSetTextureAnim(mode, face, sizex, sizey, start, length, rate);
}
default{state_entry(){start();}}

↑のように、length を 1.5 とすると、
0.5 秒後に U座標は 0.5。
1.0 秒後に U座標は 1.0。
1.5 秒後に U座標は 1.5 までいき、0.0 へ戻る
2.0 秒後に U座標は 0.5。
2.5 秒後に U座標は 1.0。
3.0 秒後に U座標は 1.5 までいき、0.0 へ戻る
というアニメーションになるわけです。

ここまでで、rate の動きがなんとなく分かってきたかもしれません。ただ注意する点として、rate は単純に 1.0 秒に動く座標の大きさではありません。rate はU座標が 1.0 までいくのにどれだけ時間がかかるかの逆数となるわけです。

start() {
	key		texture	=	"647d14d9-b739-903e-1bb3-fa2450b9c191";
	integer	mode	=	ANIM_ON | SMOOTH | LOOP;
	integer	face	=	ALL_SIDES;
	integer	sizex	=	1;
	integer	sizey	=	1;
	float	start	=	0.0;
	float	length	=	1.0;
	float	rate	=	1.0 / 10.0;
	llSetTextureAnim(0, face, 0, 0, 0.0, 0.0, 0.0);
	llSetTexture(texture, face);
	llSetTextureAnim(mode, face, sizex, sizey, start, length, rate);
}
default{state_entry(){start();}}

↑を実行してみると分かるように、10秒間かけて、テクスチャのU座標が1.0まで流れます。

それでは、ちょっと長くなったので、一旦、これまでの話をまとめます。SMOOTH を指定しないときは、ここの話は通用しないと思われます。

・integer mode
SMOOTH を入れる場合は、必ず LOOP を指定すること

・integer sizex , sizey
横、縦の分割数。
SMOOTHの場合は、分割後の1番目のみが使用される。
0 にすると 1 が自動で設定されるようです。

・float start
動きの値のオフセット値。
1ループ後にこのオフセット値から開始されます。

・float length
どれだけ最大動かすかの値
最終的に動かす最後の位置は start + length となります。
動きの値が最大値を超えると、start に戻ります。
0.0 を指定すると、 1.0 が自動で指定されるようです。

・float rate
1秒あたり、どれだけ動かすか。
例えば rate = 0.1 なら、1 秒で U座標を 1/10 動かしたりします。

今回、SCALE、 ROTATEの話はしてません。多分使うときにまた調べます。

以上です。

オマケ

後から気づいたのですが、フレームアニメだと考えると、なぜ、rateが「1.0 までいくのにどれだけ時間がかかるかの逆数」になっているのか、なども説明がつきます。

もともと、30コマ書いたテクスチャを2秒でアニメーション。つまり1秒当たり15コマを表示させたい場合、rate に 15 と設定させるはずです。

SMOOTH の場合でも考え方は同じで、もし rate に 15 を設定したまま、SMOOTH でアニメーションさせると、1秒当たり U座標が 15.0 まで進むわけです。SMOOTH を使用する場合はテクスチャを恐らく1枚の上下左右繋がった画像を使用するわけですから、rate に 15 なんて設定すると、1秒で15周も画像が目まぐるしく動いていくアニメーションになるわけです。

関連記事

  • セカンドライフでプログラム3(はねるボールを作ろう編)セカンドライフでプログラム3(はねるボールを作ろう編) こんばんは。 セカンドライフでは、どんなものでも手軽に作れてしまいます。 たとえば、右クリックメニューの制作を選ぶと、 いくつか好きな形のプリムを選べます。 上のメニューから分かるとおり、13種類ありまして、 さらにこのプリムそれぞれで、変形させたりもできて、より複雑な形を作れます。 また、プリムが基本的な形なるのですが、 1つのプリムを好きな形へ変 […] Posted in セカンドライフ制作
  • セカンドライフでHSVとRGBを相互変換してみようセカンドライフでHSVとRGBを相互変換してみよう HSVというのは、いわゆるHSV色空間のことです。 これは、Hue(色相)、Saturation(彩度)、Value(明度)を表しておりましています。 ご存知?の通りRGBの色空間から、HSVの色空間へ変換が可能でして、 これを利用すれば、今のRGBの色から、少し濃い色にしたり、逆に薄い色にしたり、 明るい色にしたり、暗い色にしたり、色相を反転させたり、いろいろで […] Posted in セカンドライフ制作
  • セカンドライフでジャンプ台を作るセカンドライフでジャンプ台を作る はじめまして。 「セカンドライフ技術系 Advent Calendar […] Posted in セカンドライフ制作
  • セカンドライフでプログラム4(アバター情報取得編)セカンドライフでプログラム4(アバター情報取得編) セカンドライフでは、 自分のアバターも他人のアバターも固有のkeyで管理しています。 そのkey情報を使って、いろいろな情報を取得できます。 というわけで、さっそくスクリプトです。 情報別に関数に分けて使いやすい形にしてみました。 下記のスクリプトは、設置するとstartGetAvatorが呼ばれて、 半径10メートルにいるアバターの情報を取得します。 […] Posted in セカンドライフ制作
  • セカンドライフでタッチすると音がでるやつセカンドライフでタッチすると音がでるやつ セカンドライフでタッチすると音がでるスクリプト。 特に連打防止機能をつけたものです。 具体的には1人に対して、 X 秒間次のクリックを防止します。 大勢からクリックされても、その1人1人に X […] Posted in セカンドライフ制作
  • セカンドライフのスクリプトのエラー処理についてセカンドライフのスクリプトのエラー処理について セカンドライフでは、スクリプトでエラーが起きるとどうなるかみなさん知っていますか。 何かエラーが出ること自体は知っていると思いますが、 そのエラーが発生後、どうなるのかはそんなに知らないと思います。 ためしに、次のようなスクリプトを実行してみましょう。 hoge() { integer x = 0; llOwnerSay("hoge_start"); x = 1 / […] Posted in セカンドライフ制作