AS3位图任意形变一步一步来(5)——简单Demo

示例,红颜色的是三角形的分割线。

混乱丑陋但是完整而且可以跑的测试代码(全部放在第一帧就可以了):

//

//-----------------------
var url:String = 'green.jpg';
var bd:BitmapData = null;

var px0,px1,px2,px3,py0,py1,py2,py3;
var pxa, pxb, pxc, pxd, pya, pyb, pyc, pyd;
var drct = true;
var steps = 20;
var interid;

// segments
var hs:Number = 8, vs:Number = 8;

// px: x coordinate
// py: y coordinate
var pxs:Array = new Array();
var pys:Array = new Array();
var trs:Array = new Array();
var nps:Array = new Array();

// four points of a rectangle, like this:
// p0--------p1
// |          |
// p2--------p3
// 

// calculate points
// 包含x坐标和y坐标,分别存储在pxs和pys数组中
// @params:
//   w: 位图宽
//   h: 位图高
//   hs: 水平分段数
//   vs: 垂直分段数
// @return:
//   void
function CalculatePoints(w:Number, h:Number, hs:Number, vs:Number):void {
    var iw:Number = w / hs;
    var ih:Number = h / vs;
    for (var h=0; h<=hs; h++) {
        pxs[h] = h * iw;
    }
    for (var v=0; v<=vs; v++) {
        pys[v] = v * ih;
    }
}

function CalculateNewPoints(p0:Point, p1:Point, p2:Point, p3:Point, hs:Number, vs:Number):void {
    var lp:Point = new Point(p0.x, p0.y);
    var rp:Point = new Point(p1.x, p1.y);

    var lxd:Number = (p2.x - p0.x)/vs;
    var lyd:Number = (p2.y - p0.y)/vs;

    var rxd:Number = (p3.x - p1.x)/vs;
    var ryd:Number = (p3.y - p1.y)/vs;
    nps = [];
    for (var v=0; v<=vs; v++) {
        lp.x = p0.x + lxd * v;
        lp.y = p0.y + lyd * v;
        rp.x = p1.x + rxd * v;
        rp.y = p1.y + ryd * v;

        nps.push(new Array());
        var xd:Number = (rp.x - lp.x)/hs;
        var yd:Number = (rp.y - lp.y)/hs;
        for (var h=0; h<=hs; h++) {
            nps[v].push(new Point(lp.x + xd * h, lp.y + yd * h));
        }
    }
    //trace(nps);
}
//CalculateNewPoints(new Point(-10, -20), new Point(40, -30), new Point(-30, 10), new Point(80, 30), 2, 2)

function CalculateMatrix(oa:Object, ob:Object):Matrix {
    var p1 = oa.p1, p2 = oa.p2, p3 = oa.p3;
    var pa = ob.p1, pb = ob.p2, pc = ob.p3;
    var mt:Matrix = new Matrix();
    mt.a = ((p3.y - p1.y)*(pb.x - pa.x) - (p2.y-p1.y)*(pc.x-pa.x))/((p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y));
    mt.b = ((p3.y - p1.y)*(pb.y - pa.y) - (p2.y-p1.y)*(pc.y-pa.y))/((p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y));
    mt.c = ((p3.x - p1.x)*(pb.x - pa.x) - (p2.x-p1.x)*(pc.x-pa.x))/((p2.y-p1.y)*(p3.x-p1.x)-(p3.y-p1.y)*(p2.x-p1.x));
    mt.d = ((p3.x - p1.x)*(pb.y - pa.y) - (p2.x-p1.x)*(pc.y-pa.y))/((p2.y-p1.y)*(p3.x-p1.x)-(p3.y-p1.y)*(p2.x-p1.x));
    //mt.tx = ((pb.x*p1.x - pa.x*p2.x)*(p3.y*p1.x-p1.y*p3.x)-(pc.x*p1.x-pa.x*p3.x)*(p2.y*p1.x-p1.y*p2.x))/((p1.x-p2.x)*(p3.y*p1.x-p1.y*p3.x)-(p1.x-p3.x)*(p2.y*p1.x-p1.y*p2.x));
    //mt.tx = ((pb.y*p1.x - pa.y*p2.x)*(p3.y*p1.x-p1.y*p3.x)-(pc.y*p1.x-pa.y*p3.x)*(p2.y*p1.x-p1.y*p2.x))/((p1.x-p2.x)*(p3.y*p1.x-p1.y*p3.x)-(p1.x-p3.x)*(p2.y*p1.x-p1.y*p2.x));
    return mt;
}

// draw triangles
function AddTriangle(bmd:BitmapData, mt:Matrix, pa:Point, pb:Point, pc:Point):void {
    var t:Shape = new Shape();
    t.graphics.lineStyle(1, 0xff0000);
    t.graphics.beginBitmapFill(bmd, mt, false, true);
    t.graphics.moveTo(pa.x, pa.y);
    t.graphics.lineTo(pb.x, pb.y);
    t.graphics.lineTo(pc.x, pc.y);
    t.graphics.endFill();
    trs.push(t);
}

function Load():void {
    var req:URLRequest = new URLRequest(url);
    var loader:Loader = new Loader();
    ConfigureListeners(loader.contentLoaderInfo);
    try {
        loader.load(req);
        //this.addChild(loader);
    } catch (err:Error) {
    }
}
function ConfigureListeners(dispatcher:IEventDispatcher):void {
    dispatcher.addEventListener(Event.COMPLETE, CompleteHandler);
    /*dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
    dispatcher.addEventListener(Event.INIT, initHandler);
    dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
    dispatcher.addEventListener(Event.OPEN, openHandler);
    dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
    dispatcher.addEventListener(Event.UNLOAD, unLoadHandler);*/
}
function CompleteHandler(evt:Event):void {
    var ld:Loader = Loader(evt.target.loader);
    var info:LoaderInfo = LoaderInfo(ld.contentLoaderInfo);
    bd = new BitmapData(info.width, info.height);
    bd.draw(info.content);

    split();
}

function split() {
    var wi:Number = bd.width;
    var hi:Number = bd.height;
    CalculatePoints(wi, hi, hs, vs);

    var m:Matrix = new Matrix();
    for (var v=0; v<vs; v++) {
        for (var h=0; h<hs; h++) {
            var p0:Point = new Point(pxs[h], pys[v]);
            var p1:Point = new Point(pxs[h+1], pys[v]);
            var p2:Point = new Point(pxs[h], pys[v+1]);
            var p3:Point = new Point(pxs[h+1], pys[v+1]);
            //trace(p0, p1, p2, p3);
            AddTriangle(bd, m, p0, p1, p2);
            AddTriangle(bd, m, p1, p2, p3);
        }
    }
    join();
}

function join() {
    var len:Number = trs.length;
    var xfix:Number = (bd.width>>2) + 10;
    var yfix:Number = (bd.height>>2) + 20;
    for (var i=0; i<len; i++) {
        this.addChild(trs[i]);
    }
    
    px0 = 0; px1 = bd.width;
    px2 = 0; px3 = bd.width;
    py0 = 0; py1 = 0; 
    py2 = bd.height;
    py3 = bd.height;
    
    pxa = 40; pxb = 240;
    pxc = 80; pxd = 480;
    pya = 40; pyb = 20;
    pyc = 320;
    pyd = 240;
    interid = setInterval(TestRender, 40);
    
    //rendNew(new Point(pxa, pya), new Point(pxb, pyb), new Point(pxc, pyc), new Point(pxd, pyd));
    //rendNew(new Point(40, 40), new Point(640, 20), new Point(80, 520), new Point(680, 440));
}

function rendNew(p0:Point, p1:Point, p2:Point, p3:Point) {
    CalculateNewPoints(p0, p1, p2, p3, hs, vs);

    var pa:Point, pb:Point, pc:Point, pd:Point;
    var m1:Matrix, m2:Matrix;
    var tid:Number = 0;
    var ps0:Point = new Point(pxs[0], pys[0]);
    var psa:Point = nps[0][0];
    for (var v=0; v<vs; v++) {
        for (var h=0; h<hs; h++) {
            p0.x = pxs[h];
            p0.y = pys[v];
            p1.x = pxs[h+1];
            p1.y = pys[v];
            p2.x = pxs[h];
            p2.y = pys[v+1];
            p3.x = pxs[h+1];
            p3.y = pys[v+1];
            pa = nps[v][h];
            pb = nps[v][h+1];
            pc = nps[v+1][h];
            pd = nps[v+1][h+1];

            tid = v*hs*2 + h*2;
            var ta = trs[tid];
            var tb = trs[tid+1];
            m1 = CalculateMatrix({p1:p0, p2:p1, p3:p2}, {p1:pa, p2:pb, p3:pc});
            if (tid > hs * 2 && h != 0) {
                m1.tx = trs[tid - hs * 2 - 1].transform.matrix.tx;
                m1.ty = trs[tid - hs * 2 - 1].transform.matrix.ty;
            } else {
                m1.tx = 0;
                m1.ty = 0;
            }
            
            m2 = CalculateMatrix({p1:p1, p2:p2, p3:p3}, {p1:pb, p2:pc, p3:pd});
            if(v > 0){
                m2.tx = trs[1].transform.matrix.tx * (h + 1) * (v + 1);
            }
            else{
                m2.tx = ((pb.x - psa.x) - (p1.x - pxs[0])) - ((pd.x - nps[v+1][0].x) - (p3.x - pxs[0]));
            }
            if(tid > 0){
                m2.ty = trs[1].transform.matrix.ty * (h + 1) * (v + 1);
            }
            else{
                m2.ty = ((pc.y - psa.y) - (p2.y - pys[0])) - ((pd.y - nps[0][h+1].y) - (p3.y - pys[0]));
            }
            ta.transform.matrix = m1;
            tb.transform.matrix = m2;
        }
    }
}

function TestRender(){
    if(Math.abs(pxa - px0) < 1){
        if(drct){
            pxa = 0;
            pya = 0;
            pxb = bd.width;
            pyb = 0;
            pxc = 0;
            pyc = bd.height;
            pxd = bd.width;
            pyd = bd.height;
        }
        else{
            pxa = 10;
            pya = 10;
            pxb = 240;
            pyb = 20;
            pxc = 20;
            pyc = 210;
            pxd = 280;
            pyd = 180;
        }
        drct = !drct;
    }
    
    px0 += (pxa - px0) / steps;
    py0 += (pya - py0) / steps;
    px1 += (pxb - px1) / steps;
    py1 += (pyb - py1) / steps;
    px2 += (pxc - px2) / steps;
    py2 += (pyc - py2) / steps;
    px3 += (pxd - px3) / steps;
    py3 += (pyd - py3) / steps;
    rendNew(new Point(px0, py0),
            new Point(px1, py1),
            new Point(px2, py2),
            new Point(px3, py3));
}

Load();

6 comments on “AS3位图任意形变一步一步来(5)——简单Demo”

  1. 没有缝隙的方法就是,在取新的网格坐标的时候都取整数值,不要直接取nps[v].push(new Point(lp.x xd * h, lp.y yd * h));

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据