[1日1Wonderfl]2日目: Papervision3D で惑星まみれ
1日1Wonderfl 2/30日目
// forked from soundkitchen's [1日1Wonderfl]1日目: Papervision3D でボールまみれ
// 1日1Wonderfl 2/30日目
package
{
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.filters.BitmapFilter;
import flash.filters.BitmapFilterQuality;
import flash.filters.ColorMatrixFilter;
import flash.filters.GlowFilter;
import flash.geom.Point;
import com.flashdynamix.utils.SWFProfiler;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.BitmapMaterial;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
[SWF(width=465, height=465, frameRate=30, backgroundColor=0x000000)]
/**
* 最近のトレンドが FLARToolKit になりつつあるので、
* そこに向かうために、とりあえずは Papervision3D を、
* 無駄なく無理なく軽いタッチで使えるようになりたい。
*/
public class Main extends Sprite
{
public static const NUM_SPHERES:uint = 15;
private var camera:Camera3D;
private var light:PointLight3D;
private var renderer:BasicRenderEngine;
private var scene:Scene3D;
private var viewport:Viewport3D;
private var root3d:DisplayObject3D;
/**
* コンストラクタ
*/
public function Main()
{
// ステージ上で会いましょう
addEventListener(Event.ADDED_TO_STAGE, initialize);
}
/**
* オブジェクトの初期化
*/
private function initialize(evt:Event):void
{
// 要らなくなったイベントは外す
removeEventListener(Event.ADDED_TO_STAGE, initialize);
// ステージの設定
stage.align = StageAlign.TOP_LEFT;
stage.quality = StageQuality.MEDIUM;
stage.scaleMode = StageScaleMode.NO_SCALE;
// SWFProfiler 仕込む
SWFProfiler.init(this);
// Papervision3D の初期化
setupPV3D();
// root の Papervision3D 版みたいなノリ
root3d = new DisplayObject3D();
scene.addChild(root3d, 'root');
var l:uint,
r:int, g:int, b:int,
hc:uint, dc:uint,
seedBmd:BitmapData,
bmd:BitmapData,
cmf:ColorMatrixFilter,
zp:Point,
//material:FlatShadeMaterial,
material:BitmapMaterial,
sphere:Sphere;
// ゼロポイント
zp = new Point();
// 元となるデータを作る
seedBmd = new BitmapData(80, 80, true, 0);
seedBmd.perlinNoise(20, 20, 8, 10, true, true, BitmapDataChannel.RED, true);
// 指定個数だけボールを作る
l = NUM_SPHERES;
while (l--)
{
// 適当に色を作ります
r = 0xff * Math.random();
g = 0xff * Math.random();
b = 0xff * Math.random();
/**
* FIXME:
* グレイスケールで生成した BitmapData に対して、
* 上で適当に生成した色を適応させるための方法として、
* 下のような ColorMatrixFilter 使った泥臭いやり方をしてる。
* 絶対にもっと良い方法があるハズ。って思いながら、
* 現状コレしか思い付かなかった :-(
* ご存知の方が居られましたら教えておくんなまし!!
*/
cmf = new ColorMatrixFilter([
r/0xff, 0, 0, 0, 0,
0, g/0xff, 0, 0, 0,
0, 0, b/0xff, 0, 0,
0, 0, 0, 1, 0, 0,
]);
// 元となる画像データを複製して
bmd = seedBmd.clone();
// 適当に作った色を適応させる
bmd.applyFilter(bmd, bmd.rect, zp, cmf);
// それぞれを合わせて明るい色を作る
hc = r << 16|g << 8|b;
// 減色して暗い色を作る
//dc = (r * .6) << 16|(g * .6) << 8|(b * .6);
// ボールを作って
//material = new FlatShadeMaterial(light, hc, dc);
material = new BitmapMaterial(bmd);
sphere = new Sphere(material, 80, 12, 9);
// 適当な位置を決めて
sphere.x = Math.random() * 1500 - 750;
sphere.y = Math.random() * 1500 - 750;
sphere.z = Math.random() * 1500 - 750;
// コレやっとかないとフィルターが適応されない
sphere.useOwnContainer = true;
// フィルターの設定
sphere.filters = [
new GlowFilter(hc, .5, 32, 32, 2, BitmapFilterQuality.LOW),
];
// 配置する
root3d.addChild(sphere, 'sphere'+String(l));
}
// イベントの設定
addEventListener(Event.ENTER_FRAME, step);
}
/**
* 毎フレーム呼ばれる処理
*/
private function step(evt:Event):void
{
var l:uint,
o:DisplayObject3D;
// 指定個分だけ回す
l = NUM_SPHERES;
while (l--)
{
o = root3d.getChildByName('sphere'+String(l));
// 取れなければスルー
if (!o) continue;
// 自転させる
o.rotationY = (o.rotationY - 2) % 360;
}
// Y 軸を軸として回す
// 公転させる
root3d.yaw(-1);
// ココで書き出し
// scene を camera で viewport なフィルムに撮る。そんな感じ
renderer.renderScene(scene, camera, viewport);
}
/**
* Papervision3D の初期化。 BasicView はココをやってくれてる
*/
private function setupPV3D():void
{
// Camera3D
// デフォルトの位置は x=0 y=0 z=-1000
camera = new Camera3D();
// PointLight3D
// デフォルトの位置は x=0 y=0 z=-1000
light = new PointLight3D();
// 上に移動
light.y = 1000;
// BasicRenderEngine
renderer = new BasicRenderEngine();
// Scene3D
scene = new Scene3D();
// Viewport3D
// x=465 y=465 resizable=true に設定
viewport = new Viewport3D(465, 465, true);
addChild(viewport);
}
}
}