[1日1Wonderfl]5日目: 惑星っぽくなってきた
1日1Wonderfl 5/30日目
とりあえず惑星にしてみた。
* 質量の計算をまるっと抜かしてるので色々と物足りない。
* あと、ぼつぼつコードに明らさまに汚ない部分が見え始めたので、
* そこらへんを簡潔に書けるように試行錯誤していく。
*
* 前回 ColorMatrixFilter を使って BitmapData の色を変更していたのを
* 今回は ColorTransform 使ってみた。が、
* どちらの方がコスト的に良いのかは未調査。近々テストしてみる。
*
* frocessing に入ってる ColorHSV はものっそいツボ。
* frocessing.color パッケージに入ってるのは全部良い感じ。な気がする。
// 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);
}
}
}