スポンサーサイト

-------- | --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

バンプマッピング

2007-11-25 | 22:37

バンプマッピングとは、面の方向(法線ベクトル)と照明の方向から面の明るさを決める事により凹凸を表現する方法。
http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20050826

下のデモでは波の面の傾きから各面の明るさを求めている。
(時間が経つと波は静まりますが、クリッくするとまた開始されます。
package {
    import flash.display.*;
    import flash.events.*;

    import org.papervision3d.core.*;	
    [SWF(width="100", height="100", backgroundColor="#ffffff")]
        public class bump extends Sprite
        {

            private var fluid:Fluid;
            private var bmd:BitmapData;
            private var range:int;
            public function bump()
            {
                stage.frameRate = 5;
                range = 100;

                this.fluid = new Fluid(range);
                //var bitmap:Bitmap = new myImage();
                bmd = new BitmapData(range,range,false,0xffffff);
                addChild(new Bitmap(bmd));

                bomb();

                stage.addEventListener(MouseEvent.CLICK, function(e:*):void{
                        bomb();
                        });

                this.addEventListener(Event.ENTER_FRAME, function(e:*):void{
                        fluid.evaluate();

                        for(var x:int = 0 ; x < range-1 ; x++){
                        for(var z:int = 0 ; z < range-1 ; z++){
                        // (x+1,y,z) - (x,y,z)
                        var v1:Number3D = new Number3D(1,
                            fluid.Buffer[x+1][z] - fluid.Buffer[x][z],
                            0);
                        // (x,y,z+1) - (x,y,z)
                        var v2:Number3D = new Number3D(0,
                            fluid.Buffer[x][z+1] - fluid.Buffer[x][z],
                            1);
                        // v1,v2から法線ベクトルを求める
                        var normal:Number3D = Number3D.cross(v1,v2);
                        normal.normalize();

                        var light:Number3D = new Number3D(range/2-x, 30, range/2);
                        light.normalize();
                        var shadow:Number = Number3D.dot(normal,light);
                        //trace(shadow);

                        bmd.setPixel(x,z,
                                (0xf0*shadow << 16) + (0xf0*shadow <<8) + 0xff*shadow);
                        }
                        }

                });
            }
            private function bomb():void{
                fluid.clearBuffer();
                var xx:int = range/2+8;
                var yy:int = range/2+8;
                for(var i:int=xx; i < xx+8; i++){
                    for(var j:int=yy; j < xx+8 ; j++){
                        fluid.Buffer[j][i] += 0.3;
                    }
                }			
            }
        }
}
internal class Fluid {

    private var w:int;
    private var h:int;

    private var buffer:Array = new Array();
    private var renderBuffer:int = 0;

    private var k1:Number;
    private var k2:Number;
    private var k3:Number;

    private var range:int;
    public function Fluid(range:int):void
    {
        this.range = range;

        w = h = range;

        clearBuffer();

        var d:Number = 1;
        var t:Number = 0.1;
        var c:Number = 3.2;
        var mu:Number = 0.0001;

        var f1:Number = c*c*t*t/(d*d);
        var f2:Number = 1/(mu*t+2);

        k1 = (4 - 8*f1)*f2;
        k2 = (mu*t-2)*f2;
        k3 = 2*f1*f2;

    }

    public function get Buffer():Array{
        return buffer[this.renderBuffer];
    }
    public function clearBuffer():void{
        buffer = [];
        // 変位が格納される3次元配列(2*w*h)
        for(var i:int = 0 ; i < 2; i++){
            var a:Array = new Array();
            for(var j:int = 0 ; j < h+1; j++){
                var aa:Array = new Array();
                for(var k:int = 0 ; k < w+1; k++)
                    aa.push(0);
                a.push(aa);
            }

            buffer.push(a);
        }
    }

    public function evaluate():void{
        for(var j:int = 0 ; j < h+1; j++){
            var crnt:Array = buffer[renderBuffer][j];
            var prev:Array = buffer[1-renderBuffer][j];
            for(var i:int = 0 ; i < w+1; i++){
                var ii:int = i;
                var jj:int = j;
                if(i == 0)
                    ii = 1
                else if (i == w)
                    ii = i - 1;
                if(j == 0)
                    jj = 1
                else if (j == h)
                    jj = j - 1;
                var currentN:Number = buffer[renderBuffer][jj + 1][ii];
                var currentP:Number = buffer[renderBuffer][jj - 1][ii];
                prev[i] =
                    k1*(crnt[ii]) + k2*prev[ii] +
                    k3*(crnt[ii+1] + crnt[ii-1] + currentN + currentP);

            }
        }

        renderBuffer = 1-renderBuffer;
    }

}

毎回全ピクセル再描画しているので遅い。
面の法線ベクトルを求めるには、面を構成する二つのベクトルの外積を求めればよい

スポンサーサイト
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。