/**
* Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/y8U1
*/
// forked from Hristiyan.Dimitrov's forked from: Sea of Clouds
// forked from tencho's Sea of Clouds
/**
* 雲海
* クリックでカメラを切り替えられます
*/
package {
import flash.display.*;
import flash.events.*;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import net.hires.debug.Stats;
import org.papervision3d.core.geom.renderables.Triangle3D;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.geom.TriangleMesh3D;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.math.NumberUV;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.Papervision3D;
import org.papervision3d.view.BasicView;
[SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "#000000")]
public class Clouds extends Sprite {
/**雲の数*/
public const CLOUD_NUM:int = 120;
/**雲画像のパターン数*/
public const PATTERN_NUM:int = 35;
/**雲のサイズ*/
public const CLOUD_SIZE:Rectangle = new Rectangle(0, 0, 400, 200);
/**perlinNoiseに使うとまずいシード値(画像に穴があくかもしれない)*/
public const ERROR_SEEDS:Array = [346, 514, 1155, 1519, 1690, 1977, 2327, 2337, 2399, 2860, 2999, 3099, 4777, 4952, 5673, 6265, 7185, 7259, 7371, 7383, 7717, 7847, 8032, 8350, 8676, 8963, 8997, 9080, 9403, 9615, 9685];
public const PI:Number = Math.PI / 180;
public var loading:LoadingScene;
public var cameraCtrl:CameraController;
public var view:BasicView;
public var canvas1:BitmapData;
public var clouds:Vector.<Cloud> = new Vector.<Cloud>();
public var drawObjects:Vector.<Cloud> = new Vector.<Cloud>();
public var cloudImages:Vector.<BitmapData> = new Vector.<BitmapData>();
public var clearColor:ColorTransform = new ColorTransform(1, 1, 1, 0);
public function Clouds() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
Display.setSize(465, 465);
stage.frameRate = 60;
stage.quality = "low";
Papervision3D.PAPERLOGGER.unregisterLogger(Papervision3D.PAPERLOGGER.traceLogger);
view = new BasicView(Display.width, Display.height, false, false, "Free");
addChild(Painter.createGradientRect(Display.width, Display.height, [Color.sky1], [1]));
canvas1 = new BitmapData(Display.width, Display.height, true, 0x00FFFFFF);
loading = new LoadingScene();
addChild(new Bitmap(canvas1));
addChild(view.viewport);
addChild(new Stats({bg:0x808080, fps:0xFFFFFF})).blendMode = BlendMode.OVERLAY;
addChild(loading);
//雲生成
for (var i:int = 0; i < CLOUD_NUM; i++) {
var cloud:Cloud = new Cloud();
clouds.push(cloud);
cloud.setPosition(Math.random() * 3500 - 1750, Math.random() * -300 + 9000, Math.random() * 4000 - 2000);
}
//カメラ初期化
cameraCtrl = new CameraController();
cameraCtrl.init(view.scene, view.camera);
//雲画像生成開始
addEventListener(Event.ENTER_FRAME, onLoading);
}
//雲画像生成中
private function onLoading(...arg):void {
for (var i:int = 0; i < 3; i++) {
if(cloudImages.length >= PATTERN_NUM){
start();
break;
}
var seed:int = Math.random() * 10000 + 1;
if (ERROR_SEEDS.indexOf(seed) >= 0) seed++;
var ct:Number = (Math.random() < 0.3)? Math.random() * 0.3 : Math.random() * 1.5;
cloudImages.push(Painter.createCloud(CLOUD_SIZE.width, CLOUD_SIZE.height, seed, ct, Color.cloudBase, Color.cloudLight, Color.cloudShadow));
loading.setProgress(cloudImages.length / PATTERN_NUM);
}
}
//レンダリング開始
private function start():void {
removeEventListener(Event.ENTER_FRAME, onLoading);
removeChild(loading);
var index:int = -1;
for each (var cloud:Cloud in clouds) {
index = ++index % cloudImages.length;
cloud.image = cloudImages[index];
}
Time.start();
addEventListener(Event.ENTER_FRAME, onEnter);
onEnter(null);
}
//毎フレーム処理
private function onEnter(e:Event):void {
var c:Cloud;
Time.update();
var time:int = Time.count;
cameraCtrl.update();
//PV3Dレンダリング
view.singleRender();
//雲を動かす
var area:int = 2000;
for each(c in clouds) {
c.z = ((c.startPosition.z + time * 0.2) + area) % (area * 2) - area;
var loop:int = int(((c.startPosition.z + time * 0.22) + area) / (area * 2));
if (c.loop != loop) {
//周回数が変化する度に雲の配置を変化させる
c.loop = loop;
c.x = Math.random() * 3500 - 1750;
c.y = Math.random() * -300 + 10000;
}
cameraCtrl.calculateScreen(c.screen, c.x, c.y, c.z);
}
//雲画像処理
canvas1.lock();
canvas1.colorTransform(Display.size, clearColor);
drawObjects.length = 0;
for each(c in clouds) {
if (c.screen.z > 10) {
c.update();
if (c.alpha <= 0) continue;
if (c.screen.x + Display.center.x < -CLOUD_SIZE.width * c.scale / 2) continue;
if (c.screen.x + Display.center.x > Display.width + CLOUD_SIZE.width * c.scale / 2) continue;
drawObjects.push(c);
}
}
drawObjects.sort(function(a:Cloud, b:Cloud):Number { return int(b.screen.z - a.screen.z); } );
//雲描画
for each(c in drawObjects) {
var target:BitmapData = canvas1;
var ct:ColorTransform = new ColorTransform(1, 1, 1, c.alpha, 0, 0, 0, 0);
var mtx:Matrix = new Matrix();
mtx.scale(c.scale, c.scale);
mtx.rotate(PI * view.camera.localRotationZ);
var dx:Number = c.scale * CLOUD_SIZE.width / 2;
var dy:Number = c.scale * CLOUD_SIZE.height / 2;
var cos:Number = Math.cos(PI * cameraCtrl.roll);
var sin:Number = Math.sin(PI * cameraCtrl.roll);
var px:Number = c.screen.x + Display.center.x - cos * dx + sin * dy;
var py:Number = c.screen.y + Display.center.y - sin * dx - cos * dy;
mtx.translate(px, py);
target.draw(c.image, mtx, ct);
}
canvas1.unlock();
}
}
}
import flash.display.*;
import flash.filters.*;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.getTimer;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.proto.CameraObject3D;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.scenes.Scene3D;
/**
* 画面サイズ
*/
class Display {
static public var width:Number;
static public var height:Number;
static public var size:Rectangle;
static public var center:Point;
static public function setSize(width:Number, height:Number):void {
Display.width = width;
Display.height = height;
size = new Rectangle(0, 0, width, height);
center = new Point(width / 2, height / 2);
}
}
/**
* 色
*/
class Color {
/**雲の色*/
static public var cloudBase:uint = 0xD7DDE5;
/**雲のハイライト色*/
static public var cloudLight:uint = 0xFFFFFF;
/**雲の影の色*/
static public var cloudShadow:uint = 0x6D8790;
/**空の色(上)*/
static public var sky1:uint = 0x1F437F;
/**空の色(下)*/
static public var sky2:uint = 0x6290C1;
}
/**
* 経過時間
*/
class Time {
static private var _start:int;
static public var count:int;
static public function update():void {
count = getTimer() - _start + 7000;
}
static public function start():void {
_start = getTimer();
}
}
/**
* 雲
*/
class Cloud {
public var x:Number = 0;
public var y:Number = 0;
public var z:Number = 0;
public var screen:Number3D = new Number3D();
public var loop:int;
public var startPosition:Number3D;
public var image:BitmapData;
public var alpha:Number;
public var scale:Number;
public function Cloud() {
}
/**
* 雲の初期位置を設定
*/
public function setPosition(x:Number, y:Number, z:Number):void {
startPosition = new Number3D(x, y, z);
this.x = x;
this.y = y;
this.z = z;
}
/**
* スケールと透明度を更新
*/
public function update():void {
scale = 600 / screen.z;
var perMin:Number = screen.z / 200;
var perMax:Number = 1 - (screen.z - 1500) / 800;
if (perMin > 1) perMin = 1;
if (perMax > 1) perMax = 1;
alpha = perMin * perMax * 2;
}
}
/**
* カメラ操作
*/
class CameraController {
private const RADIAN:Number = Math.PI / 180;
private var _calculateObject:DisplayObject3D = new DisplayObject3D();
private var _lookAtTarget:DisplayObject3D = new DisplayObject3D();
private var _camera:Camera3D;
private var _type:int = 0;
public var roll:Number;
public var angle:Number;
public var rotation:Number;
public var distance:Number;
public var lookDirection:Number;
public function CameraController() {
}
/**
* シーンとカメラを渡して初期化
*/
public function init(scene:Scene3D, camera:CameraObject3D):void {
_camera = camera as Camera3D;
scene.addChild(_calculateObject);
}
/**
* (x,y,z)のスクリーン座標を計算してscreenに設定する
*/
public function calculateScreen(screen:Number3D, x:Number, y:Number, z:Number):void {
_calculateObject.x = x;
_calculateObject.y = y;
_calculateObject.z = z;
_calculateObject.view.calculateMultiply(_camera.eye, _calculateObject.transform);
_calculateObject.calculateScreenCoords(_camera);
screen.copyFrom(_calculateObject.screen);
}
/**
* カメラ位置更新
*/
public function update():void {
_camera.position = new Number3D(1000, 10000, 1000);
}
}
class Painter {
/**
* 雲画像生成
* @param width 幅
* @param height 高さ
* @param seed ランダムシード値
* @param contrast コントラスト0~
* @param color ベースの色
* @param light 明るい色
* @param shadow 暗い色
*/
static public function createCloud(width:int, height:int, seed:int, contrast:Number = 1, color:uint = 0xFFFFFF, light:uint = 0xFFFFFF, shadow:uint = 0xDDDDDD):BitmapData {
var gradiation:Sprite = new Sprite();
var drawMatrix:Matrix = new Matrix();
drawMatrix.createGradientBox(width, height);
gradiation.graphics.beginGradientFill("radial", [0x000000, 0x000000], [0, 1], [0, 255], drawMatrix);
gradiation.graphics.drawRect(0, 0, width, height);
gradiation.graphics.endFill();
var alphaBmp:BitmapData = new BitmapData(width, height);
alphaBmp.perlinNoise(width / 3, height / 2.5, 5, seed, false, true, 1|2|4, true);
var zoom:Number = 1 + (contrast - 0.1) / (contrast + 0.9);
if (contrast < 0.1) zoom = 1;
if (contrast > 2.0) zoom = 2;
var ctMatrix:Array = [contrast + 1, 0, 0, 0, -128 * contrast, 0, contrast + 1, 0, 0, -128 * contrast, 0, 0, contrast + 1, 0, -128 * contrast, 0, 0, 0, 1, 0];
alphaBmp.draw(gradiation, new Matrix(zoom, 0, 0, zoom, -(zoom - 1) / 2 * width, -(zoom - 1) / 2 * height));
alphaBmp.applyFilter(alphaBmp, alphaBmp.rect, new Point(), new ColorMatrixFilter(ctMatrix));
var image:BitmapData = new BitmapData(width, height, true, 0xFF << 24 | color);
image.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
image.applyFilter(image, image.rect, new Point(), new GlowFilter(light, 1, 4, 4, 1, 3, true));
var bevelSize:Number = Math.min(width, height) / 30;
image.applyFilter(image, image.rect, new Point(), new BevelFilter(bevelSize, 45, light, 1, shadow, 1, bevelSize/5, bevelSize/5, 1, 3));
var image2:BitmapData = new BitmapData(width, height, true, 0);
image2.draw(Painter.createGradientRect(width, height, [light, color, shadow], [1, 0.2, 1], null, 90), null, null, BlendMode.MULTIPLY);
image2.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
image.draw(image2, null, null, BlendMode.MULTIPLY);
alphaBmp.dispose();
return image;
}
/**
* グラデーションスプライト生成
*/
static public function createGradientRect(width:Number, height:Number, colors:Array, alphas:Array, ratios:Array = null, rotation:Number = 0):Sprite {
var i:int, rts:Array = new Array();
if(ratios == null) for (i = 0; i < colors.length; i++) rts.push(int(255 * i / (colors.length - 1)));
else for (i = 0; i < ratios.length; i++) rts[i] = Math.round(ratios[i] * 255);
var sp:Sprite = new Sprite();
var mtx:Matrix = new Matrix();
mtx.createGradientBox(width, height, Math.PI / 180 * rotation, 0, 0);
if (colors.length == 1 && alphas.length == 1) sp.graphics.beginFill(colors[0], alphas[0]);
else sp.graphics.beginGradientFill("linear", colors, alphas, rts, mtx);
sp.graphics.drawRect(0, 0, width, height);
sp.graphics.endFill();
return sp;
}
}
/**
* 画像生成中画面
*/
class LoadingScene extends Sprite {
private var _lineWidth:Number = 200;
private var _loadedLine:Sprite;
public function LoadingScene() {
var bg:Sprite = addChild(Painter.createGradientRect(Display.width, Display.height, [0x000000], [1])) as Sprite;
var baseLine:Sprite = addChild(Painter.createGradientRect(_lineWidth, 2, [0x444444], [1])) as Sprite;
_loadedLine = addChild(Painter.createGradientRect(_lineWidth, 2, [0x7DA3C8], [1])) as Sprite;
baseLine.x = _loadedLine.x = int((Display.width - _lineWidth) / 2);
baseLine.y = _loadedLine.y = int((Display.height - baseLine.height) / 2);
setProgress(0);
}
public function setProgress(per:Number):void {
_loadedLine.width = _lineWidth * per;
}
}