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

simple environment mapping

+/-: zoom in/out
/**
 * Copyright zob ( http://wonderfl.net/user/zob )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wqTG
 */

package  {
    import flash.display.Sprite;
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.display.Shape;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.geom.Matrix3D;
    import flash.geom.PerspectiveProjection;
    import flash.geom.Point;
    import flash.geom.Vector3D;
    import flash.utils.*;
    import flash.geom.Utils3D;
    import flash.display.TriangleCulling;
    import flash.display.Loader;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    
    import flash.events.MouseEvent;
    import flash.events.KeyboardEvent;
    import net.hires.debug.Stats;
    import com.bit101.components.HSlider;
    import flash.geom.Matrix;
    import com.bit101.components.HUISlider;
    
    public class tunnelV02 extends Sprite
    {
        // terrain
        private var W              :int        = 20;//15;
        private var H              :int        = 30;//30;
        private var SW             :Number     = 500;
        private var SH             :Number     = 600;
        private var GW             :Number     = SW/W;
        private var GH             :Number     = SH/H;
        private var MW             :Number     = 40;
        private var MH             :Number     = 60;
        private var TW             :Number     = (MW)/W-1;
        private var TH             :Number     = (MH)/H-1;
        private var TERRIAN_MAP    :BitmapData = new BitmapData(MW, MH, false);
        private var MAP            :BitmapData;
        
        // 3D
        private var viewport       :Shape                 = new Shape();
        private var world          :Matrix3D              = new Matrix3D();
        private var projected      :Vector.<Number>       = new Vector.<Number>;
        private var projection     :PerspectiveProjection = new PerspectiveProjection();
        private var TRANS          :Matrix3D              = new Matrix3D();
        private var VERTS          :Vector.<Number>       = new Vector.<Number>;
        private var INDICES        :Vector.<int>          = new Vector.<int>;
        private var UVTS           :Vector.<Number>       = new Vector.<Number>;
        private var NORMS          :Vector.<Vector3D>     = new Vector.<Vector3D>;
        
        private var offset         :Point  = new Point();
        private var loader         :Loader;
        private var GRAPHIC_URL    :String = "http://assets.wonderfl.net/images/related_images/6/62/6212/6212aece9e0951f179ad346305a6e880f3dde0a6";//"light.jpg";
        
        // interaction
        private var matrix         :Matrix3D = new Matrix3D();
        private var dragging       :Boolean  = false;
        private var drag_mode      :Boolean  = false;
        private var old_mouse      :Point    = new Point();
        private var new_mouse      :Point    = new Point();
        private var trans          :Matrix3D = new Matrix3D();
        private var zoomer         :Number   = 750;
        private var zoomVelocity   :Number   = 0;
        private var zoomIn         :Boolean  = false;
        private var zoomOut        :Boolean  = false;
        
        // settings
        private var baseX   :Number = 5;
        private var baseY   :Number = 10;
        private var Octaves :Number = 1;
        private var speed   :Number = 1;
        
        private var baseXHSlider   :HUISlider;
        private var baseYHSlider   :HUISlider;
        private var octavesHSlider :HUISlider;
        private var speedHSlider   :HUISlider;
        
        // normal
        private var FACES    :Vector.<Face3D>   = new Vector.<Face3D>;
        private var VERTICES :Vector.<Vertex3D> = new Vector.<Vertex3D>;
        
        public function tunnelV02()
        {
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, init);
            loader.load(new URLRequest(GRAPHIC_URL), new LoaderContext(true));
        }
        
        private function init(e:Event):void
        {
            addChild(new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xCCCCCC)));
            var mouse:MovieClip = new MovieClip();
            mouse.addChild(new Bitmap(new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x0)));
            viewport.x = stage.stageWidth / 2;
            viewport.y = stage.stageHeight / 2;

            addChild(viewport);
            buildPath();
            
            MAP = Bitmap(loader.content).bitmapData;

            matrix.appendRotation(30, Vector3D.X_AXIS);
            trans.appendRotation(55, Vector3D.X_AXIS);
            trans.appendRotation(-35, Vector3D.Y_AXIS);
            
            
            var panel:Sprite = new Sprite();
            addChild(mouse);
            addChild(panel);
            addChild(new Stats());
            baseXHSlider = new HUISlider(panel, 80, 10, "baseX", updateBaseX);
            baseXHSlider.value = baseX;
            baseYHSlider = new HUISlider(panel, 80, 25, "baseY", updateBaseY);
            baseYHSlider.value = baseY;
            octavesHSlider = new HUISlider(panel, 80, 40, "Octaves", updateOctaves);
            octavesHSlider.value = (Octaves-1) * 10;
            speedHSlider = new HUISlider(panel, 80, 55, "speed", updateSpeed);
            speedHSlider.value = speed * 10;
            
            mouse.addEventListener(MouseEvent.MOUSE_DOWN, onmouseDown);
            stage.addEventListener(MouseEvent.MOUSE_UP, onmouseUp);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onmouseMove);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onkeyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, onkeyUp);
            stage.addEventListener(Event.ENTER_FRAME, processing);
            loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, init);
        }
        
        private function updateBaseX(...arg):void
        {
            baseX = baseXHSlider.value;
        }
        
        private function updateBaseY(...arg):void
        {
            baseY = baseYHSlider.value;
        }
        
        private function updateOctaves(...arg):void
        {
            Octaves = 1+(octavesHSlider.value/10)/10*9;
        }
        
        private function updateSpeed(...arg):void
        {
            speed = (speedHSlider.value/10);
        }
        
        private function buildPath():void
        {
            var w:int = 0;
            var h:int = 0;
            var xA    :Number = 0;
            var xB    :Number = 0;
            var yA    :Number = 0;
            var yB    :Number = 0;
            var zA    :Number = 0;
            var zB    :Number = 0;
            var index:int = 0;
            var i0:int = 0;
            var i1:int = 0;
            var i2:int = 0;
            var i3:int = 0;
            var faceA:Face3D;
            var faceB:Face3D;
            
            for(h = 0; h < H+1; h++)
            {
                for(w = 0; w < W+1; w++)
                {
                    VERTICES.push(new Vertex3D());
                    index = (W*h + w);
                    xA = -SW/2 + w*GW;
                    zB = -SH/2 + (h+1)*GH;
                    VERTICES[index].read(xA,yA,zB);
                }
            }
            
            for(h = 0; h < H+1; h++)
            {
                for(w = 0; w < W+1; w++)
                {
                    xA = -SW/2 + w*GW;
                    xB = -SW/2 + (w+1)*GW;
                    zA = -SH/2 + h*GH;
                    zB = -SH/2 + (h+1)*GH;
                    
                    VERTS.push(
                        xA, yA, zB
                    );
                    
                    index = (W*h + w);
                    i0 = (W*h + w);
                    i1 = (W*h + (w+1));
                    i2 = (W*(h+1) + w);
                       i3 = (W*(h+1) + (w+1));
                    VERTICES[index  ].read(xA,yA,zB);
                    
                    faceA = new Face3D();
                    faceA.vertex1 = VERTICES[i0];
                    faceA.vertex2 = VERTICES[i1];
                    faceA.vertex3 = VERTICES[i2];
                    VERTICES[i0].faces.push(faceA);
                    VERTICES[i1].faces.push(faceA);
                    VERTICES[i2].faces.push(faceA);
                    FACES.push(faceA);
                    
                    faceB = new Face3D();
                    faceB.vertex1 = VERTICES[i1];
                    faceB.vertex2 = VERTICES[i3];
                    faceB.vertex3 = VERTICES[i2];
                    VERTICES[i1].faces.push(faceB);
                    VERTICES[i3].faces.push(faceB);
                    VERTICES[i2].faces.push(faceB);
                    FACES.push(faceB);

                    if(w+1 < W && h+1 < H)
                    {
                        INDICES.push( 
                            i0,  i1,  i2, // 3
                            i1,  i3,  i2  // 6
                        );
                    }

                    UVTS.push(
                        ((w)*TW)/MW, ((h)*TH)/MH, 0
                    );
                    
                    NORMS.push(new Vector3D(), new Vector3D(), new Vector3D(), new Vector3D());
                }
            }
        }
        
        private function calcNORMS():void
        {
            var I:int = 0;
            for(I = 0; I < FACES.length; I++)
            {
                FACES[I].calculateFaceNormal();
            }
        }
        
        private function processing(e:Event):void
        {
            if(zoomIn) zoomVelocity+=2;
            if(zoomOut) zoomVelocity-=2;
            zoomVelocity *= 0.98;
            zoomer += zoomVelocity;
            
            TERRIAN_MAP.perlinNoise(baseX,baseY,Octaves,100, false, true, 8, true, [offset, offset]);
            
            var I:int = 0;
            var w:int = 0;
            var h:int = 0;
            var r:Number = 0;
            var index:int = 0;
            var i0:int = 0;
            var i1:int = 0;
            var i2:int = 0;
            var i3:int = 0;
            
            var VX:Number = 0;
            var VY:Number = 0;
            var VZ:Number = 0;
            var VLEN:Number = 0;
            
            for(h = 0; h < H; h++)
            {
                for(w = 0; w < W; w++)
                {
                    index = (W*h + w);
                    r = TERRIAN_MAP.getPixel(w*TW, h*TH) & 0xFF;
                    VERTICES[index].y = -130 + 200 * (r/0xFF);
                }
            }
            
            calcNORMS();
            
            for(I = 0; I < VERTICES.length; I++)
            {
                VERTICES[I].calculateNorm();
                VERTICES[I].norm = trans.transformVector(VERTICES[I].norm);
                VERTS[I*3  ] = VERTICES[I].x;
                VERTS[I*3+1] = VERTICES[I].y;
                VERTS[I*3+2] = VERTICES[I].z;
                UVTS[I*3  ] = 0.5+VERTICES[I].norm.x*0.5;
                UVTS[I*3+1] = 0.5+VERTICES[I].norm.y*0.5;
                UVTS[I*3+2] = 0.5+VERTICES[I].norm.z*0.5;
            }
            
            offset.y+=speed;

            world.identity();
            world.append(trans);
            
            world.appendTranslation(0, 0, zoomer);
            world.append(projection.toMatrix3D());
            
            
            var _UVTS:Vector.<Number> = new Vector.<Number>;
            matrix.transformVectors(UVTS,_UVTS);
            
            Utils3D.projectVectors(world, VERTS, projected, _UVTS);
            
            viewport.graphics.clear();
            
            viewport.graphics.beginBitmapFill(MAP, null, false, false);
            viewport.graphics.drawTriangles(projected, INDICES, _UVTS, TriangleCulling.NONE);
            viewport.graphics.endFill();
        }
        
        private function onmouseDown(e:MouseEvent):void
        {
            old_mouse.x = mouseX;
            old_mouse.y = mouseY;
            dragging = true;
        }
        
        private function onmouseMove(e:MouseEvent):void
        {
            if(dragging)
            {
                
                new_mouse.x = mouseX
                new_mouse.y = mouseY;
                
                var difference:Point = new_mouse.subtract(old_mouse);
                var vector:Vector3D = new Vector3D(difference.x, difference.y, 0);
 
                var rotationAxis:Vector3D = vector.crossProduct(new Vector3D(0,0,1));
                rotationAxis.normalize();
 
                var distance:Number = Point.distance(new_mouse, old_mouse);
                var rotationMatrix:Matrix3D = new Matrix3D();
                rotationMatrix.appendRotation(distance, rotationAxis);
                
                trans.append(rotationMatrix);
                var I:int = 0;
                var TV:Vector3D = new Vector3D();

 
                old_mouse.x = new_mouse.x;
                old_mouse.y = new_mouse.y;
            }
        }
        
        private function onmouseUp(e:MouseEvent):void
        {
            dragging = false;
        }
        
        private function onkeyDown(e:KeyboardEvent):void
        {
            switch(e.keyCode)
            {
                case 107:
                    zoomIn = true;
                    break;
                case 189:
                    zoomOut = true;
                    break;
            }
            
        }
        
        private function onkeyUp(e:KeyboardEvent):void
        {
            switch(e.keyCode)
            {
                case 107:
                    zoomIn = false;
                    break;
                case 189:
                    zoomOut = false;
                    break;
            }
            
        }
    }
    
}

import flash.geom.Vector3D;

class Vertex3D extends Vector3D
{
    public var norm:Vector3D = new Vector3D();
    public var faces:Vector.<Face3D> = new Vector.<Face3D>;
    public function Vertex3D(px:Number = 0, py:Number = 0, pz:Number = 0) {super(px,py,pz);}
    public function copy(p:*):void {x=p.x;y=p.y;z=p.z;}
    public function read(px:Number = 0, py:Number = 0, pz:Number = 0):void {x=px;y=py;z=pz;}
    public function calculateNorm():void
    {
        var I:int = 0;
        norm.x = x; norm.y = y; norm.z = z-10000;
        norm.normalize();
        for(I = 0; I < faces.length; I++)
        {
            norm.x += faces[I].norm.x;
            norm.y += faces[I].norm.y;
            norm.z += faces[I].norm.z;
        }
        norm.normalize();
    }
}

class Face3D
{
    public var vertex1:Vertex3D;
    public var vertex2:Vertex3D;
    public var vertex3:Vertex3D;
    public var norm:Vector3D = new Vector3D();
    public function Face3D() {}
    
    public function calculateFaceNormal():void
    {
        var TV2:Vector3D = vertex2.subtract(vertex1);
        var TV3:Vector3D = vertex3.subtract(vertex1);
        norm = TV2.crossProduct(Vector3D(TV3));
        norm.normalize();
    }
}