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

Bulging Color Switch Alternativa3d 8

Code Created by David E Jones
See http://davidejones.com for my work

http://davidejones.com/blog/1599-switching-colour-alternativa3d/
/**
 * Copyright davidejones ( http://wonderfl.net/user/davidejones )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/epNE
 */

// Code Created by David E Jones
// See http://davidejones.com for my work

package 
{
    import alternativa.engine3d.primitives.Box;
    import alternativa.engine3d.controllers.SimpleObjectController;
    import alternativa.engine3d.core.Camera3D;
    import alternativa.engine3d.core.Object3D;
    import alternativa.engine3d.core.Resource;
    import alternativa.engine3d.core.View;
    import alternativa.engine3d.core.events.MouseEvent3D;
    
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.display.Stage3D;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.geom.Vector3D;
    
    import com.bit101.components.Label;
    
    import alternativa.engine3d.alternativa3d;
    use namespace alternativa3d;
    
    [SWF(backgroundColor="#000000", width="465", height="465", frameRate="60")]
    
    public class Main extends Sprite 
    {
        private var scene:Object3D = new Object3D();
        private var camera:Camera3D;
        private var controller:SimpleObjectController;
        private var stage3D:Stage3D;
        private var b:Box;
        private var smat:SwitchFillMaterial;
        private var ui:Sprite = new Sprite();
        
        public function Main() 
        {
            //Wonderfl.disable_capture();
            //Wonderfl.capture_delay( 10 );
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            camera = new Camera3D(1, 10000);
            camera.view = new View(stage.stageWidth, stage.stageHeight, false, 0x1d1d1d, 0, 4);
            addChild(camera.view);
            addChild(camera.diagram);

            camera.x = -45;
            camera.y = -40;
            camera.z = 60;

            controller = new SimpleObjectController(stage, camera, 200);
            controller.lookAt(new Vector3D(0,0,0));

            scene.addChild(camera);

            stage3D = stage.stage3Ds[0];
            stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreate);
            stage3D.requestContext3D();
        }
        
        private function onContextCreate(e:Event):void 
        {
            stage3D.removeEventListener(Event.CONTEXT3D_CREATE, onContextCreate);

            var info:Label = new Label(ui, 10, 10, "http://davidejones.com");
            addChild(ui);
            
            setupSceneObjects();

            stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            stage.addEventListener(Event.RESIZE, onResize);
            onResize();
        }

        private function setupSceneObjects():void
        {
            smat = new SwitchFillMaterial(0xFF0000, 1, 40, false);

            b = new Box(50, 50, 10, 10, 10, 10, false, null);
            b.setMaterialToAllSurfaces(smat);
            scene.addChild( b );
            b.addEventListener(MouseEvent3D.CLICK, onClick);
            
            uploadResources(scene.getResources(true));
        }

        private function onClick(e:MouseEvent3D):void
        {        
            var local_point:Vector3D = new Vector3D(e.localX, e.localY, e.localZ);
            var col:uint = Math.random() * 0xFFFFFF;
            smat.switchColor(col, local_point);
        }

        private function uploadResources(resources:Vector.<Resource>):void {
            for each (var resource:Resource in resources) {
                resource.upload(stage3D.context3D);
            }
        }

        private function onEnterFrame(e:Event):void 
        {
            controller.update();
            smat.render();
            camera.render(stage3D);
        }
        
        private function onResize(e:Event = null):void {
            camera.view.width = stage.stageWidth;
            camera.view.height = stage.stageHeight;
        }
    }
}

    import alternativa.engine3d.alternativa3d;
    import alternativa.engine3d.core.Camera3D;
    import alternativa.engine3d.core.DrawUnit;
    import alternativa.engine3d.core.Light3D;
    import alternativa.engine3d.core.Object3D;
    import alternativa.engine3d.core.Renderer;
    import alternativa.engine3d.core.Transform3D;
    import alternativa.engine3d.core.VertexAttributes;
    import alternativa.engine3d.materials.compiler.Linker;
    import alternativa.engine3d.materials.compiler.Procedure;
    import alternativa.engine3d.materials.compiler.VariableType;
    import alternativa.engine3d.materials.Material;
    import alternativa.engine3d.objects.Surface;
    import alternativa.engine3d.resources.Geometry;
    import flash.events.TimerEvent;
    import flash.geom.Vector3D;
    import flash.utils.Timer;
    import flash.utils.getTimer;

    import flash.display3D.Context3D;
    import flash.display3D.Context3DBlendFactor;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.VertexBuffer3D;
    import flash.utils.Dictionary;

    use namespace alternativa3d;

    /**
     * The material fills surface with solid color in light-independent manner. Can draw a Skin with no more than 41 Joints per surface. See Skin.divide() for more details.
     *
     * @see alternativa.engine3d.objects.Skin#divide()
     */
    class SwitchFillMaterial extends Material {
        
        private static var caches:Dictionary = new Dictionary(true);
        private var cachedContext3D:Context3D;
        private var programsCache:Dictionary;

        // Vertex Procedure
        private static const SwitchFillInsetProcedure:Procedure = getSwitchFillVProcedure(true);
        private static const SwitchFillOutsetProcedure:Procedure = getSwitchFillVProcedure(false);
        private static function getSwitchFillVProcedure(inset:Boolean):Procedure
        {
            var insetMode:String = (inset) ? "" : "neg t5, t5";
            return new Procedure([
                "#a0=aPosition",
                "#a1=aNormal",
                "#c4=cOrigin",
                "#c5=cFactors",
                "#c6=cMixed",
                "#c7=cMixed2",
                
                // calculate distance between current position and distance to color change origin
                // distance = length(iwposition.xyz - origin.xyz);                
                "sub t1 a0.xyz c4.xyz",
                "dp3 t1 t1 t1",
                "sqt t1 t1",
                
                // take position of current vertex and multiply it with the world
                // iwposition = float4 (position,1) * world;
                "mul t0 a0 c0",
                
                // adjust for aesthetics  
                // distance /= 3;
                "div t1 t1 c7.x",
                
                // move factors into v2
                "mov v2 c5",
                
                // calculate factors of current colors
                // f1 = saturate((distance - timedelta) / spread);
                // f2 = saturate(-((distance - timedelta) - spread) / spread);
                //f1
                "sub t2 t1 c6.x", // distance - timedelta
                "div t2 t2 c6.y", // / spread
                "sat t2 t2",       //saturate
                "mov v2.x t2",    // factors.x
                //f2
                "sub t3 t1 c6.x", // distance - timedelta
                "sub t3 t3 c6.y", // -spread
                "neg t3 t3",      // multiply by -1 to get -((distance - timedelta) - spread)
                "div t3 t3 c6.y", // / spread
                "sat t3 t3",      // saturate
                "mov v2.y t3",    // factors.y 

                //mynormal = float4 (normal * world,1) * -sin(f1 * f2 / 2);
                "mul t4 a1 c0",   // normal * world                
                "mul t5 t2 t3",   // f1 * f2
                "div t5 t5 c6.w", // /2
                "sin t5 t5",      // sin
                insetMode,      // neg to get -sin
                "mul t6 t4 t5",  // multiply 
                
                //iwposition = float4 (position,1) + mynormal;
                "add t0 a0 t5",        
                
                // iwposition * worldViewProj;    
                "m44 o0 t0 c0",
            ], "getSwitchFillVProcedure");
        }
        
        // Fragment procedure
        static alternativa3d const getSwitchFillFProcedure:Procedure = new Procedure([
            "#c0=cCurrentColor", 
            "#c1=cNewColor", 
            //color = factors.x * currentcolor;
            "mul t0 v2.x c0",
            //color += factors.y * newcolor;
            "mul t1 v2.y c1",
            "add t0, t0, t1",
            //output
            "mov o0, t0"
        ], "getSwitchFillFProcedure");
        
        /**
         * Transparency
         */
        public var alpha:Number = 1;
        
        private var red:Number;
        private var green:Number;
        private var blue:Number;
        
        private var nred:Number;
        private var ngreen:Number;
        private var nblue:Number;
        private var nalpha:Number = 1;
        
        private var currentColor:uint;
        private var newColor:uint;
        private var origin:Vector3D = new Vector3D(0, 0, 0, 1);
        private var factors:Vector3D = new Vector3D(0, 0, 0, 1);
        private var timedelta:Number = 0.5;
        private var spread:Number = 6;
        private var startTime:Number = 0;
        private var timeStretch:Number = 40;
        private var inset:Boolean = false;
        
        /**
         * Color.
         */
        public function get color():uint {
            return (red*0xFF << 16) + (green*0xFF << 8) + blue*0xFF;
        }

        /**
         * @private
         */
        public function set color(value:uint):void {
            red = ((value >> 16) & 0xFF)/0xFF;
            green = ((value >> 8) & 0xFF)/0xFF;
            blue = (value & 0xff)/0xFF;
        }

        /**
         * Creates a new SwitchFillMaterial instance.
         * @param color Color .
         * @param alpha Transparency.
         */
        public function SwitchFillMaterial(color:uint = 0x7F7F7F, alpha:Number = 1, timeStretch:Number = 40, inset:Boolean = false) {
            this.color = color;
            this.alpha = alpha;
            this.nalpha = nalpha;
            this.inset = inset;
            
            this.timeStretch = timeStretch;
            this.currentColor = color;
            this.newColor = color;
            nred = ((this.newColor >> 16) & 0xFF)/0xFF;
            ngreen = ((this.newColor >> 8) & 0xFF)/0xFF;
            nblue = (this.newColor & 0xff) / 0xFF;
            
            startTime = getTimer();
        }
        
        public function switchColor(color:uint = 0x7F7F7F, neworigin:Vector3D=null):void
        {
            this.currentColor = this.newColor;
            red = ((this.currentColor >> 16) & 0xFF)/0xFF;
            green = ((this.currentColor >> 8) & 0xFF)/0xFF;
            blue = (this.currentColor & 0xff)/0xFF;
            
            this.newColor = color;
            nred = ((this.newColor >> 16) & 0xFF)/0xFF;
            ngreen = ((this.newColor >> 8) & 0xFF)/0xFF;
            nblue = (this.newColor & 0xff) / 0xFF;
            
            if (neworigin != null)
            {
                this.origin = neworigin;
            }
            startTime = getTimer() - 1;
        }
        
        public function render():void
        {
            timedelta = (getTimer() - this.startTime) / this.timeStretch;
        }
        
        private function setupProgram(object:Object3D):SwitchFillMaterialProgram {
            var vertexLinker:Linker = new Linker(Context3DProgramType.VERTEX);
            var positionVar:String = "aPosition";
            var normalVar:String = "aNormal";
            vertexLinker.declareVariable(positionVar, VariableType.ATTRIBUTE);
            vertexLinker.declareVariable(normalVar, VariableType.ATTRIBUTE);
            
            var proc:Procedure = (this.inset) ? SwitchFillInsetProcedure : SwitchFillOutsetProcedure;
            
            proc.assignVariableName(VariableType.CONSTANT, 0, "cProjMatrix", 4);
            if (object.transformProcedure != null) {
                positionVar = appendPositionTransformProcedure(object.transformProcedure, vertexLinker);
            }
            //vertexLinker.addProcedure(_projectProcedure);
            //vertexLinker.setInputParams(_projectProcedure, positionVar);
            vertexLinker.addProcedure(proc);
            vertexLinker.setInputParams(proc, positionVar);
            vertexLinker.setInputParams(proc, normalVar);

            var fragmentLinker:Linker = new Linker(Context3DProgramType.FRAGMENT);
            //fragmentLinker.addProcedure(outColorProcedure);
            fragmentLinker.addProcedure(getSwitchFillFProcedure);
            fragmentLinker.varyings = vertexLinker.varyings;
            return new SwitchFillMaterialProgram(vertexLinker, fragmentLinker);
        }

        /**
         * @private 
         */
        override alternativa3d function collectDraws(camera:Camera3D, surface:Surface, geometry:Geometry, lights:Vector.<Light3D>, lightsLength:int, useShadow:Boolean, objectRenderPriority:int = -1):void {
            var object:Object3D = surface.object;
            // Strams
            var positionBuffer:VertexBuffer3D = geometry.getVertexBuffer(VertexAttributes.POSITION);
            var normalsBuffer:VertexBuffer3D = geometry.getVertexBuffer(VertexAttributes.NORMAL);
            
            // Check validity
            if (positionBuffer == null) return;
            // Program

            // Renew program cache for this context
            if (camera.context3D != cachedContext3D) {
                cachedContext3D = camera.context3D;
                programsCache = caches[cachedContext3D];
                if (programsCache == null) {
                    programsCache = new Dictionary();
                    caches[cachedContext3D] = programsCache;
                }
            }

            var program:SwitchFillMaterialProgram = programsCache[object.transformProcedure];
            if (program == null) {
                program = setupProgram(object);
                program.upload(camera.context3D);
                programsCache[object.transformProcedure] = program;
            }
            // Drawcall
            var drawUnit:DrawUnit = camera.renderer.createDrawUnit(object, program.program, geometry._indexBuffer, surface.indexBegin, surface.numTriangles, program);
        
            // Streams
            // a0 a1
            drawUnit.setVertexBufferAt(program.aPosition, positionBuffer, geometry._attributesOffsets[VertexAttributes.POSITION], VertexAttributes.FORMATS[VertexAttributes.POSITION]);
            drawUnit.setVertexBufferAt(program.aNormal, normalsBuffer, geometry._attributesOffsets[VertexAttributes.NORMAL], VertexAttributes.FORMATS[VertexAttributes.NORMAL]);
                
            // Constants
            object.setTransformConstants(drawUnit, surface, program.vertexShader, camera);
            
            drawUnit.setProjectionConstants(camera, program.cProjMatrix, object.localToCameraTransform); //c0
            drawUnit.setVertexConstantsFromNumbers(program.cOrigin, origin.x, origin.y, origin.z, origin.w); //c4
            drawUnit.setVertexConstantsFromNumbers(program.cFactors, factors.x, factors.y, factors.z, factors.w); //c5
            drawUnit.setVertexConstantsFromNumbers(program.cMixed, timedelta, spread, -1, 2); //c6
            drawUnit.setVertexConstantsFromNumbers(program.cMixed2, 3, 1, 0, 0); //c7
            
            //fragment constants
            drawUnit.setFragmentConstantsFromNumbers(program.cCurrentColor, red, green, blue, alpha); //c0
            drawUnit.setFragmentConstantsFromNumbers(program.cNewColor, nred, ngreen, nblue, nalpha); //c1
            
            // Send to render
            if (alpha < 1) {
                drawUnit.blendSource = Context3DBlendFactor.SOURCE_ALPHA;
                drawUnit.blendDestination = Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA;
                camera.renderer.addDrawUnit(drawUnit, objectRenderPriority >= 0 ? objectRenderPriority : Renderer.TRANSPARENT_SORT);
            } else {
                camera.renderer.addDrawUnit(drawUnit, objectRenderPriority >= 0 ? objectRenderPriority : Renderer.OPAQUE);
            }
        }

        /**
         * @inheritDoc 
         */
        override public function clone():Material {
            var res:SwitchFillMaterial = new SwitchFillMaterial(color, alpha);
            res.clonePropertiesFrom(this);
            return res;
        }

    }

import alternativa.engine3d.materials.ShaderProgram;
import alternativa.engine3d.materials.compiler.Linker;

import flash.display3D.Context3D;

class SwitchFillMaterialProgram extends ShaderProgram {

    public var aPosition:int = -1;
    public var aNormal:int = -1;
    public var cProjMatrix:int = -1;
    public var cOrigin:int = -1;
    public var cCurrentColor:int = -1;
    public var cNewColor:int = -1;
    public var cFactors:int = -1;
    public var cMixed:int = -1;
    public var cMixed2:int = -1;

    public function SwitchFillMaterialProgram(vertex:Linker, fragment:Linker) {
        super(vertex, fragment);
    }

    override public function upload(context3D:Context3D):void {
        super.upload(context3D);

        aPosition =  vertexShader.findVariable("aPosition");
        aNormal = vertexShader.findVariable("aNormal");
        cProjMatrix = vertexShader.findVariable("cProjMatrix");
        cOrigin = vertexShader.findVariable("cOrigin");
        cFactors = vertexShader.findVariable("cFactors");
        cMixed = vertexShader.findVariable("cMixed");
        cMixed2 = vertexShader.findVariable("cMixed2");
        
        cCurrentColor = fragmentShader.findVariable("cCurrentColor");
        cNewColor = fragmentShader.findVariable("cNewColor");
    }
}