In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

PerlinNoiseの無限拡大

PerlinNoiseの無限拡大
クリックで拡大と上昇を切り替え
メモ:
静止画や単純なスクロールではCatmullRom補間とCos補間の違いが
あまり気にならなかったけれど、拡大アニメだと差が目立つ。
Cos補間では補間元のピクセルの隅のがたつきが目立ってしまうので、
CatmullRom補間の方が処理負荷が高い分、クオリティは高い。
ParlinNoiseの種を高解像度で持ってあらかじめ補間しておくなどの仕掛けを
施しておくことで、Cos補間をもう少し綺麗に見せることができるかもしれない?
// forked from Nao_u's PerlinNoiseのリアルタイムアニメーション
// forked from Nao_u's PerlinNoise生成
// 
// PerlinNoiseの無限拡大
//   クリックで拡大と上昇を切り替え
//
// メモ:
//  静止画や単純なスクロールではCatmullRom補間とCos補間の違いが
//  あまり気にならなかったけれど、拡大アニメだと差が目立つ。
//
//  Cos補間では補間元のピクセルの隅のがたつきが目立ってしまうので、
//  CatmullRom補間の方が処理負荷が高い分、クオリティは高い。
//
//  ParlinNoiseの種を高解像度で持ってあらかじめ補間しておくなどの仕掛けを
//  施しておくことで、Cos補間をもう少し綺麗に見せることができるかもしれない?
//  
// 
package {     
    import flash.display.Sprite;     
    import flash.events.*;     
    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="15")]
        
    public class FlashTest extends Sprite {     
        public function FlashTest() {     
            Main = this;     
            initialize();     
            stage.addEventListener(Event.ENTER_FRAME,update);      
            stage.addEventListener(MouseEvent.MOUSE_DOWN,MouseDown);
      
        }     
    }     
}             
    
import flash.display.Bitmap; 
import flash.display.BitmapData; 
import flash.display.Sprite;      
import flash.events.*
import flash.text.TextField;     
import flash.geom.*;
import flash.utils.getTimer;
var Main:Sprite;     
var SCREEN_W:Number = 465;
var SCREEN_H:Number = 465;
var Text:TextField    
var View: Bitmap; 
var BmpData: BitmapData; 

var BITMAP_W:int = SCREEN_W/5;
var BITMAP_H:int = SCREEN_H/5;

function initialize():void{     
    BmpData = new BitmapData(BITMAP_W, BITMAP_H, false, 0xffffff); 
    View = new Bitmap(BmpData); 
    View.x = 64.0;
    View.y = 64.0;
    View.scaleX = 3.0;
    View.scaleY = 3.0;
    Main.addChild(View);      

    Text = new TextField();     
    Text.text = "PerlinNoise生成中...";   
    Text.autoSize = "left";
    Main.addChild(Text);      

    makeRndTbl();

    AmplitudeTbl[0] = 0.4;
    AmplitudeTbl[1] = 0.20;
    AmplitudeTbl[2] = 0.104;
    AmplitudeTbl[3] = 0.0456;
    AmplitudeTbl[4] = 0.03024;
    AmplitudeTbl[5] = 0.02024;
    AmplitudeTbl[6] = 0.01024;

    setMode( 0 );
}

var Cnt:int;
var Scl:Number = 1.0;
var SclAdd:Number = 0.0;
var SclMove:Number = 0.0;
var Mode:int = 0;
var ModeText:String = "A";

var AmplitudeTbl:Vector.<Number> = new Vector.<Number>;

function MouseDown(event:MouseEvent):void{
    setMode( 1-Mode ); 
}    

function setMode( m:int ):void{
    switch( m ){
    case 0:
        ModeText = "拡大 ";
        Mode = 0;
        SclAdd = 0.03;
        SclMove = 0.0;
        break;

    case 1:
        ModeText = "上昇 ";
        Mode = 1;
        SclAdd = 0.020;
        SclMove = 0.15;
        break;
    }
}

function update(e :Event):void{     
    Cnt++;
    Scl += SclAdd;
    if( Scl >= 1.0){
        Scl -= 1.0;
    }

    var px:Number = 100 + 2.5 * Math.cos(Cnt*0.01);
    var py:Number = 100 + 2.5 * Math.sin(Cnt*0.01) + Cnt*SclMove;

    var col:Number;
    var scale:Number = 1 + (Math.pow( Scl, 1.2 ) );
    //if( (Cnt & 0x01) == 0 )
    {
        var time:int = getTimer(); 
        var cont:Number = 64;
        var mul:Number = 128 + cont;
        BmpData.lock(); 
        for( var x:int=0; x<BITMAP_W; x++ ){ 
            for( var y:int=0; y<BITMAP_H; y++ ){ 
                //col = PerlinNoise( x, y, px, py, scale, 8.0, 4 ) * mul;
                col = PerlinNoiseCos( x, y, px, py, scale, 8.0, 4 ) * mul;
                col = col + 128;
                col = col + (col<<8) + (col<<16);
                BmpData.setPixel(x, y, col); 
            }
        } 
        BmpData.unlock(); 

        var endTime:int = getTimer() - time;
        Text.text = ModeText + " 生成時間:" + endTime + "[ms]";   
    }
}  


// PerlinNoiseを生成(cos補間)
function PerlinNoiseCos( rx:Number, ry:Number, px:Number, py:Number, scl:Number, frequency:Number, octave:int ):Number{
    var total:Number = 0;
    var amplitude:Number;
    for( var i:int=0; i<octave; i++ ){
        var ts:Number = scl - 1.0;
        amplitude = AmplitudeTbl[i] * ts + 
                    AmplitudeTbl[i+1] * (1.0-ts);        

        var x:Number = px + rx/(frequency*scl) - (BITMAP_H/2)/(scl*frequency);
        var y:Number = py + ry/(frequency*scl) - (BITMAP_H/2)/(scl*frequency);
        
        var totalMul:Number = 1.0;
        if( i == 0 )        totalMul = (1.0-(scl-1.0));
        if( i == octave-1 ) totalMul = (scl-1.0);

        var ix:int = x&0xff;
        var iy:int = y&0xff;
        var tx:Number = (x - ix);
        var ty:Number = (y - iy);

        var ix_0 :int = (ix  )&0xff; 
       var ix_1 :int = (ix+1)&0xff; 
       var iy_0 :int = ((iy  )&0xff)*RNDTBL_SIZE; 
       var iy_1 :int = ((iy+1)&0xff)*RNDTBL_SIZE; 
    
        var a:Number, b:Number, t:Number; 
        var ft:Number, f:Number; 
        a = RndTbl[ ix_0 + iy_0]; 
        b = RndTbl[ ix_1 + iy_0]; 
        t = tx; 
        ft = t * Math.PI; 
        f  = (1.0 - Math.cos( ft )) * 0.5; 
        var x0:Number = a * (1.0 - f) + b * f; 

        a = RndTbl[ ix_0 + iy_1]; 
        b = RndTbl[ ix_1 + iy_1]; 
        t = tx; 
        ft = t * Math.PI; 
        f  = (1.0 - Math.cos( ft )) * 0.5; 
        var y0:Number = a * (1.0 - f) + b * f; 

        a = x0; 
        b = y0; 
        t = ty; 
        ft = t * Math.PI; 
        f  = (1.0 - Math.cos( ft )) * 0.5; 
        total += (a * (1.0 - f) + b * f) * amplitude * totalMul;

        frequency *= 0.5;
    }

    return total;
}

// PerlinNoiseを生成(CatmullRom補間)
function PerlinNoise( rx:Number, ry:Number, px:Number, py:Number, scl:Number, frequency:Number, octave:int ):Number{
    var total:Number = 0;
    var amplitude:Number;
    for( var i:int=0; i<octave; i++ ){
        var ts:Number = scl - 1.0;
        amplitude = AmplitudeTbl[i] * ts + 
                    AmplitudeTbl[i+1] * (1.0-ts);        

        var x:Number = px + rx/(frequency*scl) - (BITMAP_H/2)/(scl*frequency);
        var y:Number = py + ry/(frequency*scl) - (BITMAP_H/2)/(scl*frequency);
        
        var totalMul:Number = 1.0;
        if( i == 0 )        totalMul = (1.0-(scl-1.0));
        if( i == octave-1 ) totalMul = (scl-1.0);

     //   x = Math.abs(x);
     //   y = Math.abs(y);
        var ix:int = x&0xff;
        var iy:int = y&0xff;
        var tx:Number = (x - ix);
        var ty:Number = (y - iy);

        var ix_m1:int = (ix-1)&0xff;
        var ix_0 :int = (ix  )&0xff;
        var ix_p1:int = (ix+1)&0xff;
        var ix_p2:int = (ix+2)&0xff;
        var iy_m1:int = ((iy-1)&0xff)*RNDTBL_SIZE;
        var iy_0 :int = ((iy  )&0xff)*RNDTBL_SIZE;
        var iy_p1:int = ((iy+1)&0xff)*RNDTBL_SIZE;
        var iy_p2:int = ((iy+2)&0xff)*RNDTBL_SIZE;

        var x0:Number, x1:Number, x2:Number, x3:Number; 
        var v0:Number, v1:Number, t:Number, t2:Number, t3:Number;

        x0 = RndTbl[ ix_m1 + iy_m1];
        x1 = RndTbl[ ix_0  + iy_m1];
        x2 = RndTbl[ ix_p1 + iy_m1];
        x3 = RndTbl[ ix_p2 + iy_m1];
        t = tx;
        v0 = (x2 - x0) / 2.0;
        v1 = (x3 - x1) / 2.0;
        t2 = t * t;
        t3 = t2 * t;
        var rx0:Number = (2.0 * x1 - 2.0 * x2 + v0 + v1 ) * t3 + ( -3.0 * x1 + 3.0 * x2 - 2.0 * v0 - v1 ) * t2 + v0 * t + x1;

        x0 = RndTbl[ ix_m1 + iy_0];
        x1 = RndTbl[ ix_0  + iy_0];
        x2 = RndTbl[ ix_p1 + iy_0];
        x3 = RndTbl[ ix_p2 + iy_0];
        t = tx;
        v0 = (x2 - x0) / 2.0;
        v1 = (x3 - x1) / 2.0;
        t2 = t * t;
        t3 = t2 * t;
        var rx1:Number = (2.0 * x1 - 2.0 * x2 + v0 + v1 ) * t3 + ( -3.0 * x1 + 3.0 * x2 - 2.0 * v0 - v1 ) * t2 + v0 * t + x1;

        x0 = RndTbl[ ix_m1 + iy_p1];
        x1 = RndTbl[ ix_0  + iy_p1];
        x2 = RndTbl[ ix_p1 + iy_p1];
        x3 = RndTbl[ ix_p2 + iy_p1];
        t = tx;
        v0 = (x2 - x0) / 2.0;
        v1 = (x3 - x1) / 2.0;
        t2 = t * t;
        t3 = t2 * t;
        var rx2:Number = (2.0 * x1 - 2.0 * x2 + v0 + v1 ) * t3 + ( -3.0 * x1 + 3.0 * x2 - 2.0 * v0 - v1 ) * t2 + v0 * t + x1;

        x0 = RndTbl[ ix_m1 + iy_p2];
        x1 = RndTbl[ ix_0  + iy_p2];
        x2 = RndTbl[ ix_p1 + iy_p2];
        x3 = RndTbl[ ix_p2 + iy_p2];
        t = tx;
        v0 = (x2 - x0) / 2.0;
        v1 = (x3 - x1) / 2.0;
        t2 = t * t;
        t3 = t2 * t;
        var rx3:Number = (2.0 * x1 - 2.0 * x2 + v0 + v1 ) * t3 + ( -3.0 * x1 + 3.0 * x2 - 2.0 * v0 - v1 ) * t2 + v0 * t + x1;

        v0 = (rx2 - rx0) / 2.0;
        v1 = (rx3 - rx1) / 2.0;
        t2 = ty * ty;
        t3 = t2 * ty;
        total += 
            ((2.0 * rx1 - 2.0 * rx2 + v0 + v1 ) * t3 + 
            ( -3.0 * rx1 + 3.0 * rx2 - 2.0 * v0 - v1 ) * t2 + 
            v0 * ty + rx1) * amplitude * totalMul;

        frequency *= 0.5;
    }

    return total;
}

// 入力値( x, y ) に対応した、-1.0 ~ 1.0 の擬似乱数を生成
function rnd( x:int, y:int ):Number{
    x += y * 465 + 789221;
    x = (x>>10) ^ x;
    var ret:int = (( (x * (x * x * 15731 + 789221) + 1376312589) ) / 1000000);
    
    return (ret & 0x1ff) / 256 - 1.0;
}

var RNDTBL_SIZE:int = 256;
var RndTbl:Vector.<Number> = new Vector.<Number>;
// 256*256のランダムテーブルを生成
function makeRndTbl():void{
    for( var y:int=0; y<RNDTBL_SIZE; y++ ){
        for( var x:int=0; x<RNDTBL_SIZE; x++ ){
            RndTbl[x + y*RNDTBL_SIZE] = rnd(x,y);
        }
    }
}