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

ProjectionMatrixFilter

...
@author 9re
Get Adobe Flash player
by 9re 02 Sep 2010
/**
 * Copyright 9re ( http://wonderfl.net/user/9re )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/yWX8
 */

package 
{
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    
    /**
     * ...
     * @author 9re
     */
    [SWF(backgroundColor = "#111111", frameRate = "37")]
    public class ProjectionMatrixTest extends MovieClip
    {
        private const IMAGE_URL:String = "http://assets.wonderfl.net/images/related_images/e/ec/eca1/eca1057c7a177fd5dfa8c625e669b494bb4e85ab";
        private var _pmFilter:ProjectionMatrixFilter;
        
        private var _cvt0:ConvexTetragon;
        private var _cvt1:ConvexTetragon;
        private var _ctDomain:ConvexTetragon;
        private var _ctRegion:ConvexTetragon;
        private var _pm:ProjectionMatrix;
        private var _pointer:Vertex;
        private var _image:Sprite;
        
        public function ProjectionMatrixTest() 
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            
            _pm = new ProjectionMatrix;
            _pmFilter = new ProjectionMatrixFilter;
            
            
            var loader:Loader = new Loader;
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function ():void {
                _cvt1.addPoint(new Point(0, 0));
                _cvt1.addPoint(new Point(loader.width, 0));
                _cvt1.addPoint(new Point(loader.width, loader.height));
                _cvt1.addPoint(new Point(0, loader.height));
                
                calculateProjectionMatirx(null);
            });
            
            Vertex.COLOR = 0x999999;
            _cvt0 = new ConvexTetragon;
            _cvt0.fillAlpha = 0;
            _cvt0.addPoint(new Point(30, 40));
            _cvt0.addPoint(new Point(360, 60));
            _cvt0.addPoint(new Point(260, 240));
            _cvt0.addPoint(new Point(30, 160));
            _cvt0.draw();
            _cvt0.addEventListener(ConvexTetragon.VERTEX_MOVED, calculateProjectionMatirx);
            
            
            
            _cvt1 = new ConvexTetragon;
            
            _ctDomain = _cvt0;
            _ctRegion = _cvt1;
            
            addChild(_image = new Sprite);
            _image.addChild(loader);
            addChild(_cvt0);
            
            stage.addEventListener(Event.RESIZE, onResize);
            stage.dispatchEvent(new Event(Event.RESIZE));
            loader.load(new URLRequest(IMAGE_URL), new LoaderContext(true));
        }
        
        private function onResize(e:Event):void 
        {
            _image.graphics.beginFill(0x111111);
            _image.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            _image.graphics.endFill();
        }
        
        private function calculateProjectionMatirx(e:Event):void
        {
            var p:Point;
            
            setProjectionDomain(_ctDomain);
            setProjectionRegion(_ctRegion);
            
            _pm.calculateProjectionMatrix();
            _pm.setUpProjectionMatrixFilter(_pmFilter);
            _image.filters = [_pmFilter];
        }
        
        private function setProjectionDomain($domain:ConvexTetragon):void {
            var p:Point;
            
            p = $domain.getPointAt(0);
            _pm.setDomainA(p.x, p.y);
            p = $domain.getPointAt(1);
            _pm.setDomainB(p.x, p.y);
            p = $domain.getPointAt(2);
            _pm.setDomainC(p.x, p.y);
            p = $domain.getPointAt(3);
            _pm.setDomainD(p.x, p.y);            
        }
        
        private function setProjectionRegion($region:ConvexTetragon):void {
            var p:Point;
            
            p = $region.getPointAt(0);
            _pm.setRegionA(p.x, p.y);
            p = $region.getPointAt(1);
            _pm.setRegionB(p.x, p.y);
            p = $region.getPointAt(2);
            _pm.setRegionC(p.x, p.y);
            p = $region.getPointAt(3);
            _pm.setRegionD(p.x, p.y);
        }
    }
    
}

import flash.display.Shader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.ShaderFilter;
import flash.geom.Point;
import mx.utils.Base64Decoder;

import gs.easing.*;
import gs.TweenLite;

class ProjectionMatrixFilter extends ShaderFilter {
    public function ProjectionMatrixFilter() {
        var decoder:Base64Decoder = new Base64Decoder;
        decoder.decode(<projectionMatrixFilterKernel>
DI1vpQEAAACkFgBQcm9qZWN0aW9uTWF0cml4RmlsdGVyoAxuYW1lc3BhY2UAcXJlAKAMdmVuZG9y
AHFyZQCgCHZlcnNpb24AAQCgDGRlc2NyaXB0aW9uAEV4ZWN1dGUgUHJvamVjdGlvbiBNYXRyaXgg
RmlsdGVyIG9uIEltYWdlAKEBAgAADF9PdXRDb29yZACjAARzcmMAoQIEAQAPcmVzdWx0AKEBAQAA
AmEwAKIBZGVmYXVsdFZhbHVlAAAAAAChAQEAAAFiMACiAWRlZmF1bHRWYWx1ZQAAAAAAoQEBAgAI
YzAAogFkZWZhdWx0VmFsdWUAP4AAAKEBAQIABGExAKIBZGVmYXVsdFZhbHVlAD+AAAChAQECAAJi
MQCiAWRlZmF1bHRWYWx1ZQAAAAAAoQEBAgABYzEAogFkZWZhdWx0VmFsdWUAAAAAAKEBAQMACGEy
AKIBZGVmYXVsdFZhbHVlAAAAAAChAQEDAARiMgCiAWRlZmF1bHRWYWx1ZQA/gAAAoQEBAwACYzIA
ogFkZWZhdWx0VmFsdWUAAAAAAB0EAMEAABAAHQMAEAAAgAADAwAQBAAAAB0EACAAAMAAAwQAIAQA
QAAdBAAQAwDAAAEEABAEAIAAHQMAEAQAwAABAwAQAgAAADIEACAAAAAAKQMAEAQAgAAdAYCAAIAA
ADQAAAABgAAAHQMAEAIAQAADAwAQBAAAAB0EACACAIAAAwQAIAQAQAAdBAAQAwDAAAEEABAEAIAA
HQMAEAQAwAABAwAQAgDAAB0EACAAAIAAAwQAIAQAAAAdBAAQAADAAAMEABAEAEAAHQUAgAQAgAAB
BQCABADAAB0EACAFAAAAAQQAIAIAAAAEBAAQBACAAAMEABADAMAAHQUAgAQAwAAdAwAQAwAAAAMD
ABAEAAAAHQQAIAMAQAADBAAgBABAAB0EABADAMAAAQQAEAQAgAAdAwAQBADAAAEDABADAIAAHQQA
IAAAgAADBAAgBAAAAB0EABAAAMAAAwQAEAQAQAAdBQAgBACAAAEFACAEAMAAHQQAIAUAgAABBAAg
AgAAAAQEABAEAIAAAwQAEAMAwAAdBQBABADAADAGAPEFABAAHQEA8wYAGwA1AAAAAAAAADIBAIAA
AAAAMgEAQAAAAAAyAQAgAAAAADIBABAAAAAANgAAAAAAAAA=</projectionMatrixFilterKernel>);
        super(new Shader(decoder.drain().readObject()));
    }
    
    public function set a0(value:Number):void { shader.data.a0.value[0] = value; }
    public function set b0(value:Number):void { shader.data.b0.value[0] = value; }
    public function set c0(value:Number):void { shader.data.c0.value[0] = value; }
    public function set a1(value:Number):void { shader.data.a1.value[0] = value; }
    public function set b1(value:Number):void { shader.data.b1.value[0] = value; }
    public function set c1(value:Number):void { shader.data.c1.value[0] = value; }
    public function set a2(value:Number):void { shader.data.a2.value[0] = value; }
    public function set b2(value:Number):void { shader.data.b2.value[0] = value; }
    public function set c2(value:Number):void { shader.data.c2.value[0] = value; }
    public function get a0():Number { return shader.data.a0.value[0]; }
    public function get b0():Number { return shader.data.b0.value[0]; }
    public function get c0():Number { return shader.data.c0.value[0]; }
    public function get a1():Number { return shader.data.a1.value[0]; }
    public function get b1():Number { return shader.data.b1.value[0]; }
    public function get c1():Number { return shader.data.c1.value[0]; }
    public function get a2():Number { return shader.data.a2.value[0]; }
    public function get b2():Number { return shader.data.b2.value[0]; }
    public function get c2():Number { return shader.data.c2.value[0]; }
}


class MMatrix 
{
    private var _column:int;
    private var _row:int;
    private var _arr:Array;
        
    public function MMatrix($row:int, $column:int) 
    {
        _row = $row;
        _column = $column;
        _arr = [];
    }
        
    public function get column():int {
        return _column;
    }
        
    public function get row():int {
        return _row;
    }
        
    public function getElementAt($row:int, $column:int):Number {
        return _arr[$row * _column + $column];
    }
        
    public function setElementAt($row:int, $column:int, $value:Number):void {
        _arr[$row * _column + $column] = $value;
    }    
}

class MMatrixUtil
{        
    public static function makeMatrixFromArray($array:Array, $row:int, $column:int):MMatrix {
        var mat:MMatrix = new MMatrix($row, $column);
        var i:int, j:int;
            
            
        for (i = 0; i < $row; ++i) {
            for (j = 0; j < $column; ++j) {
                mat.setElementAt(i, j, $array[i * $column + j]);
            }
        }
        return mat;
    }
}

class HomogeneousLinearEQSystem 
{
    private var _dimension:int;
    private var _mat:MMatrix;
    private var _colInfo:Array;
        
    public function HomogeneousLinearEQSystem($array:Array):void {
        var n:int = Math.floor(Math.sqrt($array.length));
        _dimension = n;
        
        _mat = MMatrixUtil.makeMatrixFromArray($array, n, n + 1);
    }
        
    public function solve():void {
        var i:int, j:int, k:int, ii:int, ik:int;
        var t:Number, u:Number, v:Number;
        var weight:Array;
        var colInfo:Array = [];
        var rowInfo:Array = [];
            
        weight = [];
            
        for (k = 0; k <= _dimension; ++k)
            colInfo[k] = k;
            
        for (k = 0; k < _dimension; ++k) {
            rowInfo[k] = k;
                
            u = 0;
            for (j = 0; j <= _dimension; ++j) {
                t = _mat.getElementAt(k, j);
                t = (t < 0) ? -t : t;
                u = (u < t) ? t : u;
            }
            
            weight[k] = 1 / u; // suppose u != 0
        }
            
        for (k = 0; k < _dimension; ++k) {
            u = Number.NEGATIVE_INFINITY;
                
            for (i = k; i < _dimension; ++i) {
                ii = rowInfo[i];
                t = _mat.getElementAt(ii, k) * weight[ii];
                t = (t < 0) ? -t : t;
                if (t > u) {
                    u = t;
                    j = i;
                }
            }
            ik = rowInfo[j];
            if (j != k) {
                rowInfo[j] = rowInfo[k];
                rowInfo[k] = ik;
            }
            u = _mat.getElementAt(ik, k);
                
            if (u == 0) {
                //trace("u =", u);
                u = -1;
                for (j = k + 1; j <= _dimension; ++j) {
                    t = _mat.getElementAt(ik, j);
                    t = (t < 0) ? - t : t;
                    if (u < t) {
                        u = t;
                        i = j;
                    }
                }
                    
                if (u == 0) {
                        //trace("solved!");
                    //trace(rowInfo);
                    _mat = exchangeRows(_mat, rowInfo);
                    _colInfo = colInfo;
                    return;
                }
                //trace("exchange columns:", k, i);
                //trace("(ik, i) =", _mat.getElementAt(ik, i));
                // exchange columns                    
                j = colInfo[k];
                colInfo[k] = colInfo[i];
                colInfo[i] = j;
                //
                for (j = 0; j < _dimension; ++j) {
                    t = _mat.getElementAt(j, k);
                    _mat.setElementAt(j, k, _mat.getElementAt(j, i));
                    _mat.setElementAt(j, i, t);
                }
                    
                u = _mat.getElementAt(ik, k);
                //trace("after: (ik, k) =", u);
            }
                
            ik = rowInfo[k];
            for (j = k; j <= _dimension; ++j) {
                t = _mat.getElementAt(ik, j) / u;
                _mat.setElementAt(ik, j, t);
            }
                
            for (i = 0; i < _dimension; ++i) {
                if (i != k) {
                    ii = rowInfo[i];
                    u = _mat.getElementAt(ii, k);
                    for (j = k; j <= _dimension; ++j) {
                        t = _mat.getElementAt(ii, j) - _mat.getElementAt(ik, j) * u;
                        _mat.setElementAt(ii, j, t);
                    }
                }
            }
            
            //trace(k, exchangeRows(_mat, rowInfo));
                
        }
            
        //trace("solved!");
        _mat = exchangeRows(_mat, rowInfo);
        _colInfo = colInfo;
    }
        
    public function get matrix():MMatrix {
        return _mat;
    }
        
    public function get columnInfo():Array {
        return _colInfo;
    }
        
    private function exchangeRows($matrix:MMatrix, $rowInfo:Array):MMatrix {
        var copy:MMatrix = new MMatrix(_dimension, _dimension + 1);
        var i:int, j:int, ii:int;
            
        for (i = 0; i < _dimension; ++i) {
            ii = $rowInfo[i];
                
            for (j = 0; j < _dimension + 1; ++j) {
                copy.setElementAt(i, j, $matrix.getElementAt(ii, j));
            }
        }
        return copy;
    }    
}


class ProjectionMatrix 
{
    private var _dx0:Number;
    private var _dy0:Number;
    private var _dx1:Number;
    private var _dy1:Number;
    private var _dx2:Number;
    private var _dy2:Number;
    private var _dx3:Number;
    private var _dy3:Number;
        
    private var _rx0:Number;
    private var _ry0:Number;
    private var _rx1:Number;
    private var _ry1:Number;
    private var _rx2:Number;
    private var _ry2:Number;
    private var _rx3:Number;
    private var _ry3:Number;
        
    private var _coefficients:Array;
        
    private var _a0:Number;
    private var _b0:Number;
    private var _c0:Number;
        
    private var _a1:Number;
    private var _b1:Number;
    private var _c1:Number;
        
    private var _a2:Number;
    private var _b2:Number;
    private var _c2:Number;
        
    public function ProjectionMatrix() {
        
    }
        
    public function setDomainA($x:Number, $y:Number):void {
        _dx0 = $x;
        _dy0 = $y;
    }
        
    public function setDomainB($x:Number, $y:Number):void {
        _dx1 = $x;
        _dy1 = $y;
    }
        
    public function setDomainC($x:Number, $y:Number):void {
        _dx2 = $x;
        _dy2 = $y;
    }
        
    public function setDomainD($x:Number, $y:Number):void {
        _dx3 = $x;
        _dy3 = $y;
    }
        
    public function setRegionA($x:Number, $y:Number):void {
        _rx0 = $x;
        _ry0 = $y;
    }
        
    public function setRegionB($x:Number, $y:Number):void {
        _rx1 = $x;
        _ry1 = $y;
    }

    public function setRegionC($x:Number, $y:Number):void {
        _rx2 = $x;
        _ry2 = $y;
    }
        
    public function setRegionD($x:Number, $y:Number):void {
        _rx3 = $x;
        _ry3 = $y;
    }
        
    public function calculateProjectionMatrix():void {
        var hleqs:Array = [
            _dx0 * _rx0, _dy0 * _rx0, _rx0, -_dx0, -_dy0, -1, 0, 0, 0,
            _dx1 * _rx1, _dy1 * _rx1, _rx1, -_dx1, -_dy1, -1, 0, 0, 0,
            _dx2 * _rx2, _dy2 * _rx2, _rx2, -_dx2, -_dy2, -1, 0, 0, 0,
            _dx3 * _rx3, _dy3 * _rx3, _rx3, -_dx3, -_dy3, -1, 0, 0, 0,
            _dx0 * _ry0, _dy0 * _ry0, _ry0, 0, 0, 0, -_dx0, -_dy0, -1,
            _dx1 * _ry1, _dy1 * _ry1, _ry1, 0, 0, 0, -_dx1, -_dy1, -1,
            _dx2 * _ry2, _dy2 * _ry2, _ry2, 0, 0, 0, -_dx2, -_dy2, -1,
            _dx3 * _ry3, _dy3 * _ry3, _ry3, 0, 0, 0, -_dx3, -_dy3, -1,
        ];
            
        var solver:HomogeneousLinearEQSystem = new HomogeneousLinearEQSystem(hleqs);
            
        _coefficients = [];
        solver.solve();
        var conInfo:Array = solver.columnInfo;
        var solution:MMatrix = solver.matrix;
        var ii:int;
        for (var i:int = 0; i < solution.row; ++i) {
            ii = conInfo[i];
            _coefficients[ii] = - solution.getElementAt(i, solution.column - 1);
        }
        _coefficients[conInfo[solution.column - 1]] = 1;
            
        _a0 = _coefficients[0];
        _b0 = _coefficients[1];
        _c0 = _coefficients[2];
        _a1 = _coefficients[3];
        _b1 = _coefficients[4];
        _c1 = _coefficients[5];
        _a2 = _coefficients[6];
        _b2 = _coefficients[7];
        _c2 = _coefficients[8];
    }
    
    public function setUpProjectionMatrixFilter($filter:ProjectionMatrixFilter):void {
        $filter.a0 = _a0; $filter.b0 = _b0; $filter.c0 = _c0;
        $filter.a1 = _a1; $filter.b1 = _b1; $filter.c1 = _c1;
        $filter.a2 = _a2; $filter.b2 = _b2; $filter.c2 = _c2;
    }
        
    public function convert($point:Point):Point {
        var x:Number = $point.x;
        var y:Number = $point.y;
            
        return new Point(
            (_a1 * x + _b1 * y + _c1) / (_a0 * x + _b0 * y + _c0),
            (_a2 * x + _b2 * y + _c2) / (_a0 * x + _b0 * y + _c0)
        );
    }
}

class Vertex extends Sprite
{
    public static var RADIUS:Number = 5;
    public static var COLOR:uint = 0xff0000;
        
    public function Vertex($point:Point) 
    {
        x = $point.x;
        y = $point.y;
            
        graphics.beginFill(COLOR);
        graphics.drawCircle(0, 0, RADIUS);
        graphics.endFill();
    }
        
    public function get coordinate():Point {
        return new Point(x, y);
    }
        
    public function set coordinate(value:Point):void {
        x = value.x;
        y = value.y;
    }
}

class Convex extends Sprite
{
    private var _n:int;
    protected var _displayObjects:Array;
        
    public function Convex() 
    {
        _displayObjects = [];
    }
        
    public function removeAllPoints():void {
        while (_displayObjects.length > 0) {
            removeChild(_displayObjects.pop());
        }
    }
        
    public function getPointAt($index:int):Point {
        var v:Vertex = _displayObjects[$index] as Vertex;
            
        return v.coordinate;
    }
        
    public function addPoint($point:Point):void {
        _n = _displayObjects.push(addChild(new Vertex($point)));
    }
        
    public function get convexity():Boolean {
        if (_n < 4)
            return true;
            
            // _points.length > 3
        var i:int, j:int;
        var sgn:int;
        var first:Point;
        var second:Point;
        var third:Point;
        var cross:Number;
        var v:Vertex;
        for (i = 0; i < _n; ++i) {
            v = _displayObjects[i] as Vertex;
            first = v.coordinate;
            sgn = 2;
            for (j = 1; j < _n - 1; ++j) {
                v = _displayObjects[(i + j) % _n];
                second = v.coordinate;
                v = _displayObjects[(i + j + 1) % _n];
                third = v.coordinate;
                    
                second = second.subtract(first);
                third = third.subtract(first);
                cross = second.x * third.y - second.y * third.x;
                    
                if (cross == 0)
                    return false;
                    
                if (sgn == 2)
                    sgn = sign(cross);
                else if (sgn != sign(cross))
                    return false;
            }
        }
            
        return true;
    }
        
    private function sign(t:Number):int {
        return (t < 0) ? -1 : 1;
    }        
}


class ConvexTetragon extends Convex
{
    public static const VERTEX_MOVED:String = "vertex moved";
    public var color:uint = 0xffffff;
    public var fillAlpha:Number = 1.0;
    private var _prevX:Number;
    private var _prevY:Number;
    private var _v:Vertex;
        
    public function ConvexTetragon() 
    {
        //mouseEnabled = false;
        addEventListener(Event.ADDED_TO_STAGE, stageHandler, false, 0, true);
    }
        
    private function stageHandler(e:Event):void 
    {
        stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);            
    }
        
    override public function addPoint($point:Point):void 
    {
        super.addPoint($point);
            
        var v:Vertex = _displayObjects[_displayObjects.length - 1];
            
        v.buttonMode = true;
        v.tabEnabled = false;
        v.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
    }
        
    private function mouseDownHandler(e:MouseEvent):void 
    {
        _v = e.target as Vertex;
        _prevX = _v.x;
        _prevY = _v.y;
            
        stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            
        _v.startDrag();
    }
        
    private function mouseUpHandler(e:MouseEvent):void 
    {
        if (_v == null)
            return;
                
        _v.stopDrag();
            
        stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
            
        if (!convexity) {
            TweenLite.to(_v, 0.4, { x: _prevX, y:_prevY, ease:Cubic.easeOut, onComplete:removeEnterFrameHandler } );
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        } else {
            dispatchEvent(new Event(VERTEX_MOVED));
            draw();
        }
        draw();
        
        _v = null;
    }
        
    private function removeEnterFrameHandler():void
    {
        removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
    }
        
    private function enterFrameHandler(e:Event):void 
    {
        draw();
    }


    public function draw():void
    {
        var v:Vertex;
        v = _displayObjects[0] as Vertex;
        graphics.clear();
        graphics.beginFill(color, fillAlpha);
        graphics.moveTo(v.x, v.y);
            
        for (var i:int = 1; i <= 4; ++i) {
            v = _displayObjects[i & 3];
            graphics.lineTo(v.x, v.y);
        }
        graphics.endFill();
    }
        
    private function mouseMoveHandler(e:MouseEvent):void 
    {
        e.updateAfterEvent();
        draw();
    }
    
}