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

EnvMapped Plasmountains

Get Adobe Flash player
by yonatan 29 Mar 2010
/**
 * Copyright yonatan ( http://wonderfl.net/user/yonatan )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/48K6
 */

// forked from yonatan's Plasmountains
package {
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.utils.*;
    import net.hires.debug.Stats;
    import flash.net.*;
    import flash.system.*;

    [SWF(width=465,height=465,frameRate=30,backgroundColor=0x111111)]
    public class Plasmountains extends Sprite {
        private static const SIZE:int = 32;
        private static const W:int = SIZE;
        private static const H:int = SIZE;
        private static const OCTAVES:int = 5;

        private var vertices:Vector.<Number> = new Vector.<Number>(SIZE*SIZE*3, true);
        private var projected:Vector.<Number> = new Vector.<Number>(0, false);
        private var uvtData:Vector.<Number> = new Vector.<Number>(SIZE*SIZE*3, true);
        private var heightMap:BitmapData = new BitmapData(SIZE, SIZE, false);
        private var indices:Vector.<int> = new Vector.<int>((SIZE-1)*(SIZE-1)*6, true);
        private var projection:PerspectiveProjection = new PerspectiveProjection();
        private var viewport:Shape = new Shape();
        private var loader:Loader;
        private var imageBmd:BitmapData;

        private var stats:Sprite = new Sprite;

        public function Plasmountains() {
            loader = new Loader;
            loader.contentLoaderInfo.addEventListener (Event.COMPLETE, init);
            loader.addEventListener(Event.COMPLETE, init);
            loader.load(
                new URLRequest("http://farm4.static.flickr.com/3504/3790154315_a4329b2b67.jpg"), 
                // new URLRequest("http://farm4.static.flickr.com/3306/3579595198_bebb3fd5e7.jpg"), 
                // new URLRequest("http://farm4.static.flickr.com/3377/3599171765_54c53c0166.jpg"), 
                // new URLRequest("http://farm3.static.flickr.com/2249/2197367316_077c7c93c7.jpg"), 
                new LoaderContext(true));
        }
        
        public function init(e:Event):void {
            imageBmd = e.target.content.bitmapData;

            viewport.x = viewport.y = 465 / 2;
            addChild(viewport);
            projection.fieldOfView = 20;

            stats.addChild(new Bitmap(heightMap));
            stats.addChild(new Stats()).x=400;
            addChild(stats).visible = false;

            addEventListener("enterFrame", loop);
            stage.addEventListener("click", function(e:*):void { stats.visible = !stats.visible; });
        }

        private function loop(e:*):void {
            var offsets:Array = [];
            var offset:Number = -getTimer()/100;

            for(var i:uint = 0; i < OCTAVES; i++) {
                offsets.push(new Point(0, offset/(i+1)));
            }
            
            heightMap.perlinNoise(SIZE, SIZE, OCTAVES, 16, true, false, 
                BitmapDataChannel.RED | BitmapDataChannel.GREEN | BitmapDataChannel.BLUE, true,
                offsets);

            // generate vertices, uvtdata and indices
            i = 0;
            var ii:uint = 0; // indices index
            for(var y:int = 0; y < SIZE; y++) {
                for(var x:int = 0; x < SIZE; x++) {
                    vertices[i]  = -(x*2-SIZE);
                    uvtData[i++] = x/SIZE;
                    vertices[i]  = ((heightMap.getPixel(x,y) & 0xFF) - 0x80) / 0x80 * SIZE / 2;
                    uvtData[i++] = y/SIZE;
                    vertices[i]  = y*2-SIZE;
                    uvtData[i++] = 0;

                    if(x < SIZE-1 && y < SIZE-1) {
                        var i1:uint = y*SIZE+x;
                        var i2:uint = i1+SIZE;
                        
                        indices[ii++]=i1;
                        indices[ii++]=i1+1;
                        indices[ii++]=i2;
                        indices[ii++]=i1+1;
                        indices[ii++]=i2+1;
                        indices[ii++]=i2;
                    }
                }
            }

            // vertex normals without face normals -- 
            // http://www.gamedev.net/community/forums/topic.asp?topic_id=354136&whichpage=1&#2322500

            function v(x:int, y:int):Vector3D {
                return(new Vector3D(x, (heightMap.getPixel(x, y) & 0xFF)/25, y));
            }

            i=0;
            for(y=0; y < H; y++) {
                for(x=0; x < W; x++) {
                    var hn:Vector3D = v(x?x-1:x, y).subtract(v(x+1<W?x+1:x, y));
                    var vn:Vector3D = v(x, y?y-1:y).subtract(v(x, y+1<H?y+1:y));
                    var n:Vector3D = vn.crossProduct(hn);

                    n.normalize();
                    var tx:Number = ((Math.atan2(n.y,n.z)/Math.PI+1)/2);
                    var ty:Number = ((Math.atan2(n.x,n.z)/Math.PI+1)/2);

                    uvtData[i++] = tx;
                    uvtData[i++] = ty;
                    i++;
                }
            }
            
            // project
            var m:Matrix3D = new Matrix3D;
            m.appendScale(.6,.6,.6);
            m.appendRotation(38, Vector3D.X_AXIS);
            m.appendTranslation(0,-SIZE/8,-SIZE*2.3);
            m.append(projection.toMatrix3D());
            Utils3D.projectVectors(m, vertices, projected, uvtData);

            viewport.graphics.clear();
            //viewport.graphics.lineStyle(1, 0, 0.25);
            viewport.graphics.beginBitmapFill(imageBmd, null, false, true);
            viewport.graphics.drawTriangles(projected, indices, uvtData);
            viewport.graphics.endFill();
        }
    }
}