forked from: Heart

by smallflowergame forked from Heart (diff: 279)
キュン☆キュン☆
http://mathworld.wolfram.com/HeartSurface.html
♥0 | Line 276 | Modified 2010-08-11 14:59:07 | MIT License
play

ActionScript3 source code

/**
 * Copyright smallflowergame ( http://wonderfl.net/user/smallflowergame )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/kjWJ
 */

// forked from yuuganisakase's Heart
//キュン☆キュン☆
//http://mathworld.wolfram.com/HeartSurface.html

package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.events.Event;
    import flash.filters.BlurFilter;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import org.papervision3d.core.effects.BitmapLayerEffect;
    import org.papervision3d.core.effects.utils.BitmapClearMode;
    import org.papervision3d.core.geom.Pixels;
    import org.papervision3d.core.geom.renderables.Pixel3D;
    import org.papervision3d.core.geom.renderables.Vertex3D;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.view.BasicView;
    import org.papervision3d.view.layer.BitmapEffectLayer;
    
    [SWF(width="465", height="465", backgroundColor="0x000000", frameRate="20")]
    public class Heart extends BasicView
    {
        private const ZERO_POINT:Point = new Point(0, 0);
        private const BLUR:BlurFilter = new BlurFilter(4, 4, 1);
    
        private var hm:HeartMath = new HeartMath();
        private var counter:Number = -1;
        private var pixels:Pixels;
        private var _canvas:BitmapData;;
        private var rect:Rectangle;
        private var _matrix:Matrix;
        public function Heart()
        {
Wonderfl.capture_delay(15);
            super(465/4, 465/4,true, true, "Target");
            var layer:BitmapEffectLayer = new BitmapEffectLayer(viewport,465,465,false);// , true, 0, BitmapClearMode.CLEAR_PRE, true);
            layer.clearBeforeRender = true;
            layer.addEffect(new BitmapLayerEffect(new BlurFilter(4,4,2), true));
            viewport.containerSprite.addLayer(layer);
            pixels = new Pixels(layer);
            
            scene.addChild(pixels);
            pixels.rotationZ = 90;
            pixels.z = -470;
            pixels.y = -310;
            camera.target = pixels;
            
//http://wonderfl.net/code/bc7f3d9b6c859128e6c0d944c50c0451de0e3067        
            _canvas =new BitmapData(465 / 4, 465 / 4, false, 0x000000);
            var bmp:Bitmap=new Bitmap(_canvas, "never", true);
            bmp.scaleX=bmp.scaleY=4;
            bmp.smoothing=true;
            bmp.blendMode = BlendMode.ADD;
            bmp.alpha = 0.7;
            viewport.addChild(bmp);
            _matrix = new Matrix(0.25, 0, 0, 0.25);
/*            for (var i:Number = -span; i < span; i+=0.1) 
            {
                for (var j:Number = -span; j < span; j+=Step) 
                {
                    divideCals( -1.1, 1.1, i, j);
                }
            }
*/            
            startRendering();
            addEventListener(Event.ENTER_FRAME, onFrame);
        }
        private function divideCals(start:Number, end:Number, ii:Number, jj:Number):void
        {
            var ind:Array = [0]
            var n:Number = 0;
            const sc:Number = 250;
            const Max:Number = 40;
            const divNum:int = 6;
            var s:Number = (end - start) / divNum;
            const lSize:int = 8;
            const color:uint = 0x77ff88aa;
                for (var i:int = 0; i < divNum; i++) 
                {
                    ind[0] = 0;
                    n = hm.secant(start + i * s, start + i * s + s, ii, jj, Max, 0.000001, 0.0000001, ind);

                    if (ind[0] != -1 && n > start && n < end && jj < 0.8 && jj > -0.8) {
                        var p:Pixel3D = new Pixel3D(color, n * sc, jj * sc * 1.5, ii * sc * 0.4);
                        pixels.addPixel3D(p);
                    }
                    ind[0] = 0;
                    n = hm.secant2(start + i * s, start + i * s + s, ii, jj, Max, 0.000001, 0.0000001, ind);
                    if (ind[0] != -1 && n > 0.8 && n < 0.8) {
                        p = new Pixel3D(color, jj * sc, n * sc * 1.5, ii * sc * 0.4);
                        pixels.addPixel3D(p);

                    }
                    ind[0] = 0;
                    n = hm.secant3(start + i * s, start + i * s + s, ii, jj, Max, 0.000001, 0.0000001, ind);
                    if (ind[0] != -1 && n > start && n < end && ii < 0.8 && ii > -0.8 ){
                         p= new Pixel3D(color, jj * sc, ii * sc * 1.5, n * sc * 0.4);
                        pixels.addPixel3D(p);

                    }

                }
        }
        
        private function onFrame(e:Event):void
        {
            _canvas.applyFilter(_canvas, _canvas.rect, ZERO_POINT, BLUR);
            _canvas.draw(viewport,_matrix);
            if(counter < 1){
                                    counter += 0.03;
   
                for (var j:Number = -1; j < 1; j+=0.02) 
                {
                    divideCals( -1.1, 1.1, counter, j);
                }
            }
            pixels.rotationX += 0.7;
        }
    }
}

class HeartMath
{
    
    private function pow(b:Number, p:Number):Number
    {
        return Math.pow(b, p);
    }

    private function Fx(xx:Number, yy:Number, zz:Number):Number
    {
        return pow(2*(pow(xx, 2) + 2*pow(yy, 2) + pow(zz, 2) - 1), 3) - 
                pow(xx, 2) * pow(zz, 3)/10 - 
                pow(yy, 2) * pow(zz, 3);
    }
    //secant method using three factor x,y,z
    public function secant(start1:Number, start2:Number,
                            y0:Number, z0:Number,
                            max:int, 
                            eps1:Number, eps2:Number,
                            ind:Array):Number
    {
        var f:Number, f1:Number, f2:Number, x:Number;
        var count:int = 0;
        ind[0] = 0;
        f1 = Fx(y0,z0,start1);
        f2 = Fx( y0,z0,start2);
        if (Math.abs(f1) < eps2)
        {
            x = start1;
        }else {
            if (Math.abs(f2) < eps2)
            {
                x = start2;
            }else {
                while (ind[0] == 0) 
                {
                    count += 1;
                    if (Math.abs(f2 - f1) < eps2)
                    {
                        ind[0] = -1;
                    }else {
                        x = start2 - f2 * (start2 - start1) / (f2 - f1);
                        f = Fx(y0, z0,x);
                        if (Math.abs(f) < eps2 ||
                            Math.abs(start2 - start1) < eps1 ||
                            Math.abs(start2 - start1) < eps1 * Math.abs(start2))
                        {
                            ind[0] = count;
                        }else {
                            if (count < max)
                            {
                                if (f1 * f2 < 0)
                                {
                                    start2 = x;
                                    f2 = f;
                                }else {
                                    start1 = x;
                                    f1 = f;
                                }
                            }else {
                                ind[0] = -1;
                            }
                        }
                    }
                }
            }
        }
        return x;
    }
    public function secant2(start1:Number, start2:Number,
                            x0:Number, z0:Number,
                            max:int, 
                            eps1:Number, eps2:Number,
                            ind:Array):Number
    {
        var f:Number, f1:Number, f2:Number, y:Number;
        var count:int = 0;
        ind[0] = 0;
        f1 = Fx(x0,start1,z0);
        f2 = Fx(x0,start2,z0);
        if (Math.abs(f1) < eps2)
        {
            y = start1;
        }else {
            if (Math.abs(f2) < eps2)
            {
                y = start2;
            }else {
                while (ind[0] == 0) 
                {
                    count += 1;
                    if (Math.abs(f2 - f1) < eps2)
                    {
                        ind[0] = -1;
                    }else {
                        y = start2 - f2 * (start2 - start1) / (f2 - f1);
                        f = Fx(x0,y, z0);
                        if (Math.abs(f) < eps2 ||
                            Math.abs(start2 - start1) < eps1 ||
                            Math.abs(start2 - start1) < eps1 * Math.abs(start2))
                        {
                            ind[0] = count;
                        }else {
                            if (count < max)
                            {
                                if (f1 * f2 < 0)
                                {
                                    start2 = y;
                                    f2 = f;
                                }else {
                                    start1 = y;
                                    f1 = f;
                                }
                            }else {
                                ind[0] = -1;
                            }
                        }
                    }
                }
            }
        }
        return y;
    }
    public function secant3(start1:Number, start2:Number,
                            y0:Number, z0:Number,
                            max:int, 
                            eps1:Number, eps2:Number,
                            ind:Array):Number
    {
        var f:Number, f1:Number, f2:Number, x:Number;
        var count:int = 0;
        ind[0] = 0;
        f1 = Fx(start1,y0,z0);
        f2 = Fx(start2,y0,z0);
        if (Math.abs(f1) < eps2)
        {
            x = start1;
        }else {
            if (Math.abs(f2) < eps2)
            {
                x = start2;
            }else {
                while (ind[0] == 0) 
                {
                    count += 1;
                    if (Math.abs(f2 - f1) < eps2)
                    {
                        ind[0] = -1;
                    }else {
                        x = start2 - f2 * (start2 - start1) / (f2 - f1);
                        f = Fx(x,y0, z0);
                        if (Math.abs(f) < eps2 ||
                            Math.abs(start2 - start1) < eps1 ||
                            Math.abs(start2 - start1) < eps1 * Math.abs(start2))
                        {
                            ind[0] = count;
                        }else {
                            if (count < max)
                            {
                                if (f1 * f2 < 0)
                                {
                                    start2 = x;
                                    f2 = f;
                                }else {
                                    start1 = x;
                                    f1 = f;
                                }
                            }else {
                                ind[0] = -1;
                            }
                        }
                    }
                }
            }
        }
        return x;
    }
}