Sprite3Dクラスについて。
Meshではなく、Object3Dの継承クラス。GeometryやSurfaceは持っていないようだ。
常にカメラのほうを向くPlaneのようなもの。3次元上の回転情報を持たないので計算が速くなるとか。
3Dの世界ではビルボード、なんて呼ばれてたり。
なにをするかっていうと、ポリゴンを描く代わりにそれっぽいテクスチャを貼ったビルボードを使うことでそれなりに見栄えがし、かつ軽い。らしい。
あとはパーティクルにも使うみたい。
このデモは実は地面以外は全部Sprite3D。
ポリゴンの代わりとして球体を、パーティクルとして音符をSprite3Dで表現してる。
球体はどの角度から見ても同じに見えるからよくビルボードが使われるとか。もっとうまいテクスチャ貼ったら完全に球に見えるよきっと。
public function Sprite3D(width:Number, height:Number, material:Material = null)
ビルボードの幅と高さ、マテリアルを引数に取る。
マテリアルはmateriaプロパティで後から動的変更できるようだ。
いくつか特徴があり、まずSprite3D自体はリソースをもっていない。getResouces()してみると、マテリアルのぶんしか取得できない。頂点データは転送しなくていいんだね。レンダリングするときにまとめてなんとかするのかね。
そしてなぜかクリッピングできない。普通のオブジェクトなら近づきすぎたり、遠ざかりすぎたりするとカメラのコンストラクタで指定した値に応じて画面右上のステータスのDRWとTRIが減るのだが、上のデモではそうならない。なんでだろう。
package { import alternativa.engine3d.materials.TextureMaterial; import alternativa.engine3d.objects.Sprite3D; import alternativa.engine3d.resources.BitmapTextureResource; import flash.display.BitmapData; import flash.geom.Point; /** * ... * @author */ [SWF(width="550",height="400")] public class Main extends AlBasicView { [Embed(source="on4.png")] static private const EmbedTexture:Class; // private const sourceBd:BitmapData = new EmbedTexture().bitmapData; ; private const numClef:uint = 200; private const range:Number = 3000; public function Main():void { stage.frameRate = 60; camera.view.backgroundColor = 0x333333; new RoundCameraController(camera, stage); // for (var i:int = 0; i < numClef; i++){ var sp:Sprite3D = createClef(0xFFFFFF * Math.random()); sp.x = getRand(); sp.y = getRand(); sp.z = getRand(); } // request(); } private function createClef(color:uint):Sprite3D { var base:BitmapData = new BitmapData(sourceBd.width, sourceBd.height, false, color); var dest:BitmapData = new BitmapData(sourceBd.width, sourceBd.height, true, 0xff000000); dest.copyPixels(base, base.rect, new Point(), sourceBd); var material:TextureMaterial = new TextureMaterial(new BitmapTextureResource(dest)); material.useDiffuseAlphaChannel = true; var sp:Sprite3D = new Sprite3D(100, 100, material); scene.addChild(sp); return sp; } private function getRand():Number { return (Math.random() - 0.5) * range; } } }
簡単なのでサクッと。
getRand()は0を中心に±range/2の一様乱数を返すメソッド。
private function createClef(color:uint):Sprite3D {
var base:BitmapData = new BitmapData(sourceBd.width, sourceBd.height, false, color);
var dest:BitmapData = new BitmapData(sourceBd.width, sourceBd.height, true, 0xff000000);
dest.copyPixels(base, base.rect, new Point(), sourceBd);
var material:TextureMaterial = new TextureMaterial(new BitmapTextureResource(dest));
material.useDiffuseAlphaChannel = true;
var sp:Sprite3D = new Sprite3D(100, 100, material);
scene.addChild(sp);
return sp;
}
まず色をuintで受け取る。
sourceBdはあらかじめ作っておいた音符のBitmapData。音符の部分が黒(透明度FF)で、その他が透明色(透明度0)で塗られたもの。
これと同じ大きさで受け取った色のBitmapDataをbaseとして作る。
次に実際に使うBitmapDataをdestとして作る。透明度をサポートし、FFにしておく。
このdestにbaseをcopyPixels()する。この時アルファ設定(第4引数)をsourceBdにする。これで音符の部分は設定色かつ透明度FFでその他の部分は透明度0のBitmapDataができる。
このBitmapDataをもとにTextureMaterialを作り、useDiffuseAlphaChannelをtrueにすることでアルファチャンネルが使えるようにする。
このマテリアルでSprite3Dを作り、sceneにaddChild()する。そしてSprite3Dをretuenするメソッドだ。
つまり指定色の音符のSprite3Dを作って返すメソッド。
for (var i:int = 0; i < numClef; i++){
var sp:Sprite3D = createClef(0xFFFFFF * Math.random());
sp.x = getRand();
sp.y = getRand();
sp.z = getRand();
}
あとはコンストラクタでランダムな色でたくさん作ってランダムな位置に配置する。それだけ。
軽いかっていうと微妙かも。煙とかはビルボードのパーティクルで作るらしいんだけどできるのかそんなこと。
Author:9ballsyn
ActionScriptについて
最近はMolehill