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

TUNAMI

3Dライブラリに入る前の3D基礎勉強その3。
3D照明の計算部分がまだちゃんと理解できてないですが。。

クリックで津波が起こせます。
Get Adobe Flash player
by rettuce 04 Mar 2011
    Embed
/**
 * Copyright rettuce ( http://wonderfl.net/user/rettuce )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/nNVw
 */

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.ColorTransform;
    import flash.events.MouseEvent;    
    import caurina.transitions.Tweener;
    
    [SWF(width = 465, height = 465, backgroundColor = 0x000000, frameRate = 60)]
    
    /**
     * ...
     * @author rettuce
     * 
     */
    public class Main extends Sprite
    {
        private var NUM:Number = 50;    // 1辺のブロック数
        private var WID:Number = 200;    // ブロック幅
        private var _pointArr:Array = [];
        private var _triangleArr:Array = [];
        private var _vpX:Number = stage.stageWidth/2;    // 消失点
        private var _vpY:Number = stage.stageHeight/2;    // 消失点
        private var _fl:Number = 330;
        
        public function Main() {
            init();
        }
        
        public function init():void
        {
            var N:Number = NUM+1;
            
            /*  3DPoint 生成  */
            for (var i:int = 0; i < N*N; i++) {
                var xpos:Number = WID * (i % N) - (NUM)*WID/2;
                var zpos:Number = -WID * Math.floor(i / N) + (NUM)*WID/2;
                _pointArr[i] = new Point3D(xpos, _fl+WID*Math.random(), zpos);
            }
            for (i = 0; i < _pointArr.length; i++ ) {
                _pointArr[i].setVanishingPoint(_vpX, _vpY);        // 消失点の指定
                _pointArr[i].setCenter(0, 1000, NUM*WID/2);        // 中心点の指定
            }
            
            /*  トライアングル 生成  */            
            var index:int = 0;
            for (i = 0; i < N*NUM; i++) {
                if ( (i % NUM)-Math.floor(i / N)  != 0 || (i % N) == 0  ) {
                    _triangleArr[index]      = new Triangle(_pointArr[i], _pointArr[i + N +1 ], _pointArr[i + N], 0x0066FF);
                    _triangleArr[index + 1] = new Triangle(_pointArr[i], _pointArr[i + 1], _pointArr[i + N +1]  , 0x0066FF);
                    index += 2;
                }
            }
            var light:Light = new Light();
            for (i = 0; i < _triangleArr.length; i++ ) {
                _triangleArr[i].light = light;                        // 3D照明
            }
            
            stage.addEventListener(MouseEvent.CLICK, clickHandler );
            addEventListener(Event.ENTER_FRAME, enterframeHandler);
        }
        
        private var _cnt:int = 0;
        private function clickHandler(e:MouseEvent):void
        {
            for (var i:int = 0; i < _pointArr.length; i++ ) {
                if ( i % (NUM+1) == _cnt ) {
                    var t:Point3D = _pointArr[ i ];
                    Tweener.addTween( t, { y : 600 * Math.random(), time:0.4, delay:0.3 } );
                    Tweener.addTween( t, { y : -600 * Math.random(), time:0.8, delay:1 } );
                    Tweener.addTween( t, { y : 300*Math.random()+200, time:1.5 , delay:2 } );
                }
            }
            _cnt++;
            if (_cnt < NUM+1) {
                Tweener.addTween( t, { time:0.2, onComplete:function(){  clickHandler(null) }} );
            } else {
                _cnt = 0;
            }
        }
        
        private function enterframeHandler(e:Event):void
        {
            var angleY:Number = 0.001;
            for(var i:int = 0; i<_pointArr.length; i++){
                _pointArr[i].rotateY(angleY);
            }
            
            _triangleArr.sortOn("depth", Array.DESCENDING | Array.NUMERIC );
            graphics.clear();
            
            for (i = 0; i < _triangleArr.length; i++) {
                if (_triangleArr[i].depth > -NUM*WID/2 ) {
                    _triangleArr[i].draw(graphics);                    
                }
            }            
        }
    }
}

class Point3D
{
        public var fl:Number = 250;
        private var vpX:Number = 0;
        private var vpY:Number = 0;
        private var cX:Number = 0;
        private var cY:Number = 0;
        private var cZ:Number = 0;
        public var x:Number = 0;
        public var y:Number = 0;
        public var z:Number = 0;
        
        public function Point3D(x:Number=0, y:Number=0, z:Number=0)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        
        public function setVanishingPoint(vpX:Number, vpY:Number):void
        {
            this.vpX = vpX;
            this.vpY = vpY;
        }
        
        public function setCenter(cX:Number, cY:Number, cZ:Number=0):void
        {
            this.cX = cX;
            this.cY = cY;
            this.cZ = cZ;
        }
        
        public function get screenX():Number
        {
            var scale:Number = fl / (fl + z + cZ);
            return vpX + (cX + x) * scale;
        }
        
        public function get screenY():Number
        {
            var scale:Number = fl / (fl + z + cZ);
            return vpY + (cY + y) * scale;
        }
        
        public function rotateX(angleX:Number):void
        {
            var cosX:Number = Math.cos(angleX);
            var sinX:Number = Math.sin(angleX);
            
            var y1:Number = y * cosX - z * sinX;
            var z1:Number = z * cosX + y * sinX;
            
            y = y1;
            z = z1;
        }
        
        public function rotateY(angleY:Number):void
        {
            var cosY:Number = Math.cos(angleY);
            var sinY:Number = Math.sin(angleY);
            
            var x1:Number = x * cosY - z * sinY;
            var z1:Number = z * cosY + x * sinY;
            
            x = x1;
            z = z1;
        }
        
        public function rotateZ(angleZ:Number):void
        {
            var cosZ:Number = Math.cos(angleZ);
            var sinZ:Number = Math.sin(angleZ);
            
            var x1:Number = x * cosZ - y * sinZ;
            var y1:Number = y * cosZ + x * sinZ;
            
            x = x1;
            y = y1;
        }
}

class Light
{
        public var x:Number;
        public var y:Number;
        public var z:Number;
        private var _brightness:Number;
        
        public function Light(x:Number = -100, y:Number = -100, z:Number = -100, brightness:Number = 1)
        {
            this.x = x;
            this.y = y;
            this.z = z;
            this.brightness = brightness;
        }
        
        public function set brightness(b:Number):void
        {
            _brightness = Math.max(b, 0);
            _brightness = Math.min(_brightness, 1);
        }
        
        public function get brightness():Number
        {
            return _brightness;
        }
}

import flash.display.Graphics;
class Triangle
{
        private var pointA:Point3D;
        private var pointB:Point3D;
        private var pointC:Point3D;
        private var color:uint;
        public var light:Light;
        
        public function Triangle(a:Point3D, b:Point3D, c:Point3D, color:uint=0xFF0000 )
        {
            pointA = a;
            pointB = b;
            pointC = c;
            this.color = color;
        }
        
        public function draw(g:Graphics):void
        {
            if (isBackFace()) return
            
            g.beginFill(getAdjustedColor());
//            g.lineStyle(1, 0xFFFFFF);
            g.moveTo(pointA.screenX, pointA.screenY);
            g.lineTo(pointB.screenX, pointB.screenY);
            g.lineTo(pointC.screenX, pointC.screenY);
            g.lineTo(pointA.screenX, pointA.screenY);
            g.endFill();
        }
        
        private function getAdjustedColor():uint
        {
            var red:Number = color >> 16;
            var green:Number = color >> 8 & 0xff;
            var blue:Number =color & 0xff;
            
            var lightFactor:Number = getLightFactor();
            
            red *= lightFactor;
            green *= lightFactor;
            blue *= lightFactor;
            
            return red << 16 | green << 8 | blue;
        }
        
        private function getLightFactor():Number
        {
            var ab:Object = new Object();
            ab.x = pointA.x - pointB.x;
            ab.y = pointA.y - pointB.y;
            ab.z = pointA.z - pointB.z;
            
            var bc:Object = new Object();
            bc.x = pointB.x - pointC.x;
            bc.y = pointB.y - pointC.y;
            bc.z = pointB.z - pointC.z;
            
            var norm:Object = new Object();
            norm.x = (ab.y * bc.z) - (ab.z * bc.y);
            norm.y = -((ab.x * bc.z) - (ab.z * bc.x));
            norm.z = (ab.x * bc.y) - (ab.y * bc.x);
            
            var dotProd:Number = norm.x * light.x + 
                                 norm.y * light.y + 
                                 norm.z * light.z;
            
            var normMag:Number = Math.sqrt(norm.x * norm.x + 
                                           norm.y * norm.y +
                                           norm.z * norm.z);
            
            var lightMag:Number = Math.sqrt(light.x * light.x +

                                            light.y * light.y +
                                            light.z * light.z);
            
            return (Math.acos(dotProd / (normMag * lightMag)) / Math.PI)
                    * light.brightness;
        }
        
        private function isBackFace():Boolean
        {
            var cax:Number = pointC.screenX - pointA.screenX;
            var cay:Number = pointC.screenY - pointA.screenY;
            var bcx:Number = pointB.screenX - pointC.screenX;
            var bcy:Number = pointB.screenY - pointC.screenY;            
            return cax * bcy > cay * bcx;
        }
        
        public function get depth():Number
        {
            var zpos:Number = Math.min(pointA.z, pointB.z );
            zpos = Math.min(zpos, pointC.z);
            return zpos;
        }
        
}