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

テクスチャ生成実験2

Perlin noizeを変調してテクスチャを生成
クリックで別パターンを生成
Get Adobe Flash player
by Nao_u 09 Apr 2011
/**
 * Copyright Nao_u ( http://wonderfl.net/user/Nao_u )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/ym6j
 */

// 
// Perlin noizeを変調してテクスチャを生成
//
// クリックで別パターンを生成
//
//
package {     
    import flash.display.Sprite;     
    import flash.events.*;     
    [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="30")]      
        
    public class FlashTest extends Sprite {     
        public function FlashTest() {     
            Main = this;     
            initialize();     
            stage.addEventListener(Event.ENTER_FRAME,update);      
            stage.addEventListener(MouseEvent.MOUSE_DOWN, function (event:MouseEvent):void{ Text.text = "生成中..."; Cnt=0 });       
        }     
    }     
}             

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/2;
var BITMAP_H:int = SCREEN_H/2;
var Cnt:int;
var Frequency:Number = 32;
var Base:Number = 0;
var Type:int = 0;
var bAbs:Boolean = true;

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

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

function resetTexture():void{     
    BmpData.lock(); 
    for( var x:int=0; x<BITMAP_W; x++ ){ 
        for( var y:int=0; y<BITMAP_H; y++ ){ 
            var col:int = 0xffffff;
            BmpData.setPixel(x, y, col); 
        }
    } 
    BmpData.unlock(); 
}

function createTexture(Type:int, frequency:Number, base:Number, bAbs:Boolean):void{     
    var func:Function;
    switch( Type ){
        case 0: func = Noise0; break;
        case 1: func = Noise1; break;
        case 2: func = Noise2; break;
        case 3: func = Noise3; break;
    }

    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++ ){ 
            var col:int;
            col = func( x, y, frequency, 0.4, 4, bAbs, base) * mul;
            if( bAbs )  col = col + 32;
            else        col = col + 128;
            col = col + (col<<8) + (col<<16);
            BmpData.setPixel(x, y, col); 
        }
    } 
    BmpData.unlock(); 
}

function update(e :Event):void{     
    Cnt++;
    if( Cnt == 1 ){
        resetTexture();
    }
    if( Cnt == 2 ){
        var time:int = getTimer(); 
        createTexture(Type%4,Frequency, Base, bAbs);
        var endTime:int = getTimer() - time;
        Text.text = "生成時間:" + endTime + "[ms]";   
        
        Type++;
        Frequency = 16 + 64 * Math.abs(rnd( Type*13, Type*27 ));
        Base = 16 + 240 * Math.abs(rnd( (Frequency+Type)*27, Type*13 ));
        if( Type%5 && ((Type-3)%7) ) bAbs = true;
        else                      bAbs = false;
    }
}  

// Noiseを生成(ランダムで変調)
function Noise0( x:Number, y:Number, frequency:Number, presistence:Number, octave:int, bAbs:Boolean, base:Number ):Number{
    var total:Number = 0;
    var amplitude:Number = presistence;
    var n:Number;
    for( var i:int=0; i<octave; i++ ){
        var sx:Number = x;
        var sy:Number = y;
        x += 48*makeNoise( sx, sy, frequency, amplitude, bAbs  );
        y += 48*makeNoise( sx, sy, frequency, amplitude, bAbs  );
        n = makeNoise( base+x, base+y, frequency, amplitude, bAbs  );
        if( bAbs ) n *= 1.9;
        total += n;

        amplitude *= presistence;
        frequency *= 0.50;
    }
    return total;
}

// Noiseを生成(sin変調)
function Noise1( x:Number, y:Number, frequency:Number, presistence:Number, octave:int, bAbs:Boolean, base:Number ):Number{
    var total:Number = 0;
    var amplitude:Number = presistence;
    var n:Number;
    
    for( var i:int=0; i<octave; i++ ){
        var sx:Number = 0.5 + x / BITMAP_W * 3.14 *4;
        var sy:Number = y / BITMAP_H * 3.14 *3;
        sx = sx + Math.sin(sy) ;
        n = makeNoise( base+x+5.5*Math.sin(sy), base+y+17.5*Math.sin(sx), frequency, amplitude, bAbs  );
        if( bAbs ) n *= 1.9;
        total += n;
        amplitude *= presistence;
        frequency *= 0.5;
    }
    return total;
}

// PerlinNoiseを生成(通常)
function Noise2( x:Number, y:Number, frequency:Number, presistence:Number, octave:int, bAbs:Boolean, base:Number ):Number{
    var total:Number = 0;
    var amplitude:Number = presistence;
    
    for( var i:int=0; i<octave; i++ ){
        total += makeNoise( base+x, base+y, frequency, amplitude, bAbs );
        amplitude *= presistence;
        frequency *= 0.5;
    }
    return total;
}

// Noiseを生成(回転)
function Noise3( x:Number, y:Number, frequency:Number, presistence:Number, octave:int, bAbs:Boolean, base:Number  ):Number{
    var total:Number = 0;
    var amplitude:Number = presistence;
    frequency *= 2;    
    presistence *= 2;
    base += 1000;

    for( var i:int=0; i<octave; i++ ){
        var sx:Number = x;
        var sy:Number = y;
        x = sx *  1.5 + sy * -1.1;
        y = sx *  1.1 + sy *  1.5;
        total += 0.85*(makeNoise( 4000+x, 4000+y, frequency, amplitude, bAbs  ));

        amplitude *= presistence;
        frequency *= 1.00;
    }
    return (total);
}

// 周波数に対応したノイズを生成
function makeNoise( x:Number, y:Number, frequency:Number, amplitude:Number, bAbs:Boolean ):Number{
    if( bAbs ) return Math.abs(rndSmooth(x/frequency,y/frequency) * amplitude);
    else       return (rndSmooth(x/frequency,y/frequency) * amplitude);

}

// 入力値( x, y ) に対応した、滑らかな擬似乱数を生成 (補間の結果-1.0を下回ったり、1.0を超えることがある)
function rndSmooth( x:Number, y:Number ):Number{
    var tx:Number = (x - Math.floor(x));
    var txInv:Number = 1.0 - tx;
    var ty:Number = (y - Math.floor(y));
    var tyInv:Number = 1.0 - ty;
    var ix:int = x;
    var iy:int = y;

    // cos補間
    var x0:Number = interpolate( rnd(ix, iy),   rnd(ix+1, iy),   tx );
    var x1:Number = interpolate( rnd(ix, iy+1), rnd(ix+1, iy+1), tx );
    return interpolate( x0, x1, ty );
}

// a から b をcosでなめらかに補間
function interpolate( a:Number, b:Number, t:Number ):Number{
    var ft:Number = t * Math.PI;
    var f:Number = (1.0 - Math.cos( ft )) * 0.5;
    return a * (1.0 - f) + b * f;
}

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