flash on 2009-4-18
プロシージャルテクスチャ生成実験
//
// プロシージャルテクスチャ生成実験
//
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);
}
}
}
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;
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);
}
var Cnt:int;
function update(e :Event):void{
Cnt++;
if( Cnt == 2 ){
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++ ){
var col:int = PerlinNoise( x, y, 32.0, 0.4, 4 ) * mul;
col = col + 32;// + 128;
col = col + (col<<8) + (col<<16);
BmpData.setPixel(x, y, col);
}
}
BmpData.unlock();
var endTime:int = getTimer() - time;
Text.text = "生成時間:" + endTime + "[ms]";
}
}
// Noiseを生成
function PerlinNoise3( x:Number, y:Number, frequency:Number, presistence:Number, octave:int ):Number{
var total:Number = 0;
var amplitude:Number = presistence;
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) ;
// sy = sy + Math.sin(sx) ;
// total += 1.5*makeNoise( 100+x+5.5*Math.sin(sy), 100+y+17.5*Math.sin(sx), frequency, amplitude );
var sx:Number = x;
var sy:Number = y;
x += 48*makeNoise( sx, sy, frequency*1.0, amplitude );
y += 48*makeNoise( sx, sy, frequency*1.0, amplitude );
total += 1.9*makeNoise( x, y, frequency, amplitude );
amplitude *= presistence;
frequency *= 0.50;
}
return total;
}
// Noiseを生成
function PerlinNoise2( x:Number, y:Number, frequency:Number, presistence:Number, octave:int ):Number{
var total:Number = 0;
var amplitude:Number = presistence;
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) ;
// sy = sy + Math.sin(sx) ;
total += 1.5*makeNoise( 100+x+5.5*Math.sin(sy), 100+y+17.5*Math.sin(sx), frequency, amplitude );
amplitude *= presistence;
frequency *= 0.5;
}
return total;
}
// PerlinNoiseを生成
function PerlinNoise( x:Number, y:Number, frequency:Number, presistence:Number, octave:int ):Number{
var total:Number = 0;
var amplitude:Number = presistence;
for( var i:int=0; i<octave; i++ ){
total += makeNoise( x, y, frequency, amplitude );
amplitude *= presistence;
frequency *= 0.5;
}
// if( total < -1.0 ) total = -1.0;
// if( total > 1.0 ) total = 1.0;
return total;
}
// 周波数に対応したノイズを生成
function makeNoise( x:Number, y:Number, frequency:Number, amplitude:Number ):Number{
return Math.abs (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;
}