// forked from soundkitchen's [1日1Wonderfl]4日目: 惑星なりそこない // 1日1Wonderfl 5/30日目 /** * とりあえず惑星にしてみた。 * 質量の計算をまるっと抜かしてるので色々と物足りない。 * あと、ぼつぼつコードに明らさまに汚ない部分が見え始めたので、 * そこらへんを簡潔に書けるように試行錯誤していく。 * * 前回 ColorMatrixFilter を使って BitmapData の色を変更していたのを * 今回は ColorTransform 使ってみた。が、 * どちらの方がコスト的に良いのかは未調査。近々テストしてみる。 * * frocessing に入ってる ColorHSV はものっそいツボ。 * frocessing.color パッケージに入ってるのは全部良い感じ。な気がする。 */ 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.GlowFilter; import flash.geom.ColorTransform; import com.flashdynamix.utils.SWFProfiler; import frocessing.color.ColorHSV; import org.papervision3d.cameras.Camera3D; import org.papervision3d.core.data.UserData; import org.papervision3d.materials.BitmapMaterial; import org.papervision3d.materials.special.ParticleMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.objects.special.ParticleField; import org.papervision3d.render.BasicRenderEngine; import org.papervision3d.scenes.Scene3D; import org.papervision3d.view.Viewport3D; [SWF(width=465, height=465, frameRate=30, backgroundColor=0x000000)] /** * document class. */ public class Main extends Sprite { public static const NUM_PLANETS:uint = 6; public static const CAMERA_DISTANCE:uint = 2000; private var camera:Camera3D; private var renderer:BasicRenderEngine; private var scene:Scene3D; private var viewport:Viewport3D; private var root3d:DisplayObject3D; private var sun:Sphere; private var planets:Vector.<DisplayObject3D>; public function Main() { addEventListener(Event.ADDED_TO_STAGE, initialize); } private function initialize(evt:Event):void { removeEventListener(Event.ADDED_TO_STAGE, initialize); // setup stage. stage.align = StageAlign.TOP_LEFT; stage.quality = StageQuality.HIGH; stage.scaleMode = StageScaleMode.NO_SCALE; // set profiler. SWFProfiler.init(this); // setup pv3d. setupPV3D(); // create background particle field. createBackground(); // create sun object. createSun(); // create planet object(s). createPlanets(); addEventListener(Event.ENTER_FRAME, step); } /** * setup papervision3d. */ private function setupPV3D():void { // camera. camera = new Camera3D(); camera.zoom = 1.5; camera.focus = 200; camera.target = DisplayObject3D.ZERO; // renderer. renderer = new BasicRenderEngine(); // scene. scene = new Scene3D(); // viewport. viewport = new Viewport3D(465, 465, true); addChild(viewport); // create root container object. root3d = new DisplayObject3D(); scene.addChild(root3d); } /** * create background particle field. */ private function createBackground():void { var mat:ParticleMaterial, obj:ParticleField; mat = new ParticleMaterial(0xa8a8a8, .7, ParticleMaterial.SHAPE_CIRCLE); obj = new ParticleField(mat, 500, 4, 4000, 4000, 4000); root3d.addChild(obj); } /** * create sphere object as sun. */ private function createSun():void { var bmd:BitmapData, mat:BitmapMaterial; bmd = new BitmapData(465, 465, true, 0); bmd.perlinNoise(465/8, 465/8, 8, 10, true, true, BitmapDataChannel.RED); mat = new BitmapMaterial(bmd); sun = new Sphere(mat, 800, 32, 24); sun.useOwnContainer = true; sun.filters = [ new GlowFilter(0xff0000, .6, 64, 64, 2), ]; root3d.addChild(sun); } /** * create sphere object as planet(s). */ private function createPlanets():void { var i:uint, s:Number, angle:Number, distance:Number, src:BitmapData, bmd:BitmapData, mat:BitmapMaterial, wrapper:DisplayObject3D, obj:Sphere, hsv:ColorHSV; s = 100; src = new BitmapData(s, s, true, 0); src.perlinNoise(s/8, s/8, 8, 20, true, true, BitmapDataChannel.RED, true); hsv = new ColorHSV(0, 1, 1, 1); planets = new Vector.<DisplayObject3D>(NUM_PLANETS, true); for (i=0; i<NUM_PLANETS; i++) { angle = Math.random() * Math.PI * 2; distance = Math.random() * 2000 + 1000; hsv.h = angle / Math.PI * 180; bmd = src.clone(); bmd.colorTransform(bmd.rect, new ColorTransform(hsv.r/0xff, hsv.g/0xff, hsv.b/0xff, hsv.a, 0, 0, 0, 0)); mat = new BitmapMaterial(bmd); obj = new Sphere(mat, 100, 12, 9); obj.x = Math.cos(angle) * distance; obj.z = Math.sin(angle) * distance; obj.useOwnContainer = true; obj.filters = [ new GlowFilter(hsv.value, .6, 16, 16, 2), ]; // TODO: fix this poor logic. obj.userData = new UserData({ 'accel': (3000 - distance) / 2500 }); wrapper = new DisplayObject3D(); wrapper.addChild(obj); root3d.addChild(wrapper); planets[i] = obj; } } /** * will execute triggered enter frame event. */ private function step(evt:Event):void { var angleX:Number, angleY:Number, accel:Number, obj:DisplayObject3D; angleX = (mouseX / stage.stageWidth) * Math.PI * 2; angleY = (mouseY / stage.stageHeight) * Math.PI * 2; // TODO: fix this poor code. sun.rotationY -= .5; for each (obj in planets) { accel = obj.userData.data['accel']; obj.rotationY -= 2 * accel; DisplayObject3D(obj.parent).rotationY -= 1 * accel; } camera.x += (Math.sin(angleX) * CAMERA_DISTANCE - camera.x) * .2; camera.z += (Math.cos(angleX) * CAMERA_DISTANCE - camera.z) * .2; camera.y += (Math.sin(angleY) * CAMERA_DISTANCE - camera.y) * .2; renderer.renderScene(scene, camera, viewport); } } } [1日1Wonderfl]5日目: 惑星っぽくなってきた