// 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); } } } [1日1Wonderfl]2日目: Papervision3D で惑星まみれ