最近、なぜかハマッてる??サウンドビジュアライザーですが、今回はpapaervision3Dを利用したビジュアライザーを作りました。
まぁサウンドの解析は、前回説明してるので今回はpaparvisionでのポイントとなるとおもわれる部分をメモ。
Cubeオブジェクトの中心軸をずらす
今回はpaprvision3Dのcubeオブジェクトの高さを変化させるビジュアライザーですが、基本papervisionで作成するオブジェクトの軸はそのオブジェクトの中心になる(MovieClipでいう中心)
なので高さを変化させるとその軸を中心に変化するのでそのままだと上下に伸縮してしまうので中心軸をオブジェクトの底辺に移動させる必要がある
必要のない部分ははしょりますが、Cubeオブジェクトを作成して、例えば今回は高さを200ピクセルにしているので中心軸のy座標は100になる位置です。今回はCubeオブジェクトの底辺(下)に中心軸を移動させたいのでまずはCubeオブジェクトを作成したときに頂点の座標が含まれる配列「geometry.vertices」があるのでその配列に含まれている頂点座標のy軸をfor each文で処理して下記のようにする。データ型はVertex3Dです。
var m:ColorMaterial = new ColorMaterial(Math.random() * 0xffffff);
m.interactive = true;
var mlist:MaterialsList = new MaterialsList( {all:m } );
var o:Cube = new Cube(mlist, 20, 20, 200, 1, 1, 1);
o.useOwnContainer = true;
for each(var g:Vertex3D in o.geometry.vertices) {
//中心軸のy座標を+100してあげることで中心軸が底辺(下に移動する)
g.y += 100;
}
}
上記のようにすれば中心軸がCubeの底辺に移動するのでこれで高さを変化させればそれっぽくなります。
滑らかにするために減速式を使う
前回のビジュアライザーはサウンドデータをそのままMovieClipの変化値に使用してるが今回は高さが変化するときに少しでも滑らかに変化するようにしてみた
基本的な処理の流れ(EnerFrame内)
直前までのオブジェクトの高さを保持する
var now:Number = t.scaleY;
readFloat()メソッドで取得したサウンドデータをif文で「0」か「1」に決める。こちらを減速式のターゲットに使用する
var lr:Number = bytes.readFloat();
if (lr > 1) lr = 1;
if (lr < 0) lr = 0;
上記で取得した減速のターゲットの値から現在のオブジェクトの高さの値を引いて再度おなじ変数:nowに代入することでオブジェクトの高さを更新してあげる。変数:smoothは減速させるための摩擦値で「0.5」を指定
now += (lr - now) * smooth;
t.scaleY = now;
まとめた部分
var bytes:ByteArray = new ByteArray();
SoundMixer.computeSpectrum(bytes, false, 0);
for (var i:int = 0; i < rllist.length; i++) {
for (var j:int = 0; j < rllist[i].length; j++) {
var t:Cube = rllist[i][j] as Cube;
var now:Number = t.scaleY;
var nowAlpha:Number = t.alpha;
//
var lr:Number = bytes.readFloat();
if (lr > 1) lr = 1;
if (lr < 0) lr = 0;
now += (lr - now) * smooth;
nowAlpha += (lr - nowAlpha) * smooth;
t.scaleY = now;
t.alpha = Math.max(0.4, nowAlpha);
}
}
とまぁこんな感じでメモっとく。今回はアルファも変化させてますが、あんまし変わってないし方法は同じなのではしょるがアルファ値はサウンドデータによっては0になっては困るので前回同様「Math.max」を使用して0.4以下にしないようにしてます
補足* Cubeオブジェクトのアルファ値の設定
Cubeの場合は直接アルファの設定ができないので「useOwnContainer」のプロパティを「true」にする
var o:Cube = new Cube(mlist, 20, 20, 200, 1, 1, 1);
o.useOwnContainer = true;
ただしtureに設定すると「OBJECT_CLICK と OBJECT_DOUBLE_CLICK」のイベントが使えなくなるので別のイベントで代用する必要があるので注意です。ネットで検索すればたくさん出てきます。