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

Sphere of Cubes

できれば衝突判定も入れたいね
Get Adobe Flash player
by uwi 12 Aug 2010
/**
 * Copyright uwi ( http://wonderfl.net/user/uwi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/h1A8
 */

// できれば衝突判定も入れたいね
package {
    import flash.display.*;
    import flash.events.Event;
    import flash.filters.*;
    import flash.geom.*;
    import flash.text.TextField;
    import frocessing.color.*;
    import net.hires.debug.Stats;
    import org.libspark.betweenas3.*;
    import org.libspark.betweenas3.easing.*; 
    import org.libspark.betweenas3.tweens.*;
    import org.papervision3d.core.math.*;
    import org.papervision3d.core.proto.*;
    import org.papervision3d.materials.*;
    import org.papervision3d.materials.utils.*;
    import org.papervision3d.objects.primitives.*;
    import org.papervision3d.view.BasicView;
    import org.papervision3d.objects.*;

    [SWF(backgroundColor="0x000000", frameRate="60")]
    public class PV3D extends BasicView {
        private var _tf : TextField;
        
        private var _t : Number = 0; // ステップ数
        private var _u : Number = 240; // キューブの色のH成分。移動完了したら変化する。
        
        private var _last : ITween; // 最終tween. 移動終了のフラグ用
        private var _wait : Number = 1.0; // tweenの移動時間単位
        private var N : uint = 16; // 初期状態の一辺のキューブの個数
        
        private var _starts : Array; // 開始点たち
        private var _ends : Array; // 終了点たち
        private var _cubes : Array; // キューブたち
        private const STARY : Number = 200; // 球の中心のY座標
        
        private var _face : BitmapData; // キューブ表面の模様
        
        public function PV3D() {
            super(0, 0, true, false);
            graphics.beginFill(0);
            graphics.drawRect(0, 0, 465, 465);
            graphics.endFill();
            
            _tf = new TextField();
//            addChild(_tf);
            _tf.textColor = 0xffffff;
            _tf.width = 100;
            _tf.height = 465;
            
            initLogic(); 
            init3D();
            initTween();

            startRendering();
        }
        
        private function initLogic() : void
        {
            _starts = [];
            // 適当に正方形
            var i : int, j : int, k : int;
            for(i = 0;i < N;i++){
                for(j = 0;j < N;j++){
                    _starts.push([i * 50 - 50 * (N / 2), -300, j * 50 - 50 * (N / 2)]);
                }
            }
            // shuffle
            for(i = 0;i < N*N - 1;i++){
                j = Math.random() * (N*N - i - 1) + i + 1;
                var d : Array = _starts[i]; _starts[i] = _starts[j]; _starts[j] = d;
            }

            _ends = [];
            // 球の半径の昇順にソート
            for(i = -4;i <= 4;i++){
                for(j = -4;j <= 4;j++){
                    for(k = -4;k <= 4;k++){
                        if(i == 0 && j == 0 && k == 0)continue;
                        _ends.push({x:i*50, y:j*50+STARY, z:k*50, r:i*i+j*j+k*k});
                    }
                }
            }
            _ends.sortOn("r", Array.NUMERIC);
        }
        
        private function init3D() : void
        {
            _face = new BitmapData(100, 100, false, 0x000000);
            var mat : MaterialObject3D = new BitmapMaterial(_face);
            var ml : MaterialsList = new MaterialsList({all:mat});
            
            _cubes = [];
            for(var i : uint = 0;i < N * N;i++){
                var cube : Cube = new Cube(ml, 50, 50, 50);
                _cubes.push(cube);
                cube.x = _starts[i][0];
                cube.y = _starts[i][1];
                cube.z = _starts[i][2];
                scene.addChild(cube);
            } 
//            addChild(new Stats());

            _camera = new OperableSphereCamera(new Number3D(0, 0, 0), 700, new Number3D(0, 0, 1), new Number3D(0, 1, 0), stage, 0.005, 0.005);
        }
        
        private function paint(bmd : BitmapData, c : uint) : void
        {
            bmd.lock();
            if(_last.isPlaying)bmd.fillRect(bmd.rect, 0);
            bmd.fillRect(new Rectangle(0, 0, 99, 6), c);
            bmd.fillRect(new Rectangle(0, 0, 6, 99), c);
            bmd.fillRect(new Rectangle(0, 93, 99, 99), c);
            bmd.fillRect(new Rectangle(93, 0, 99, 99), c);
            bmd.applyFilter(bmd, bmd.rect, new Point(), new BlurFilter(15, 15));
            bmd.unlock();
        }

        private function initTween() : void
        {
            // tweenを定義
            var cap : uint = 1;
            var left : int = 1;
            for(var i : uint = 0;i < N*N;i++){
                _last = BetweenAS3.delay(
                    BetweenAS3.serial(
                        BetweenAS3.to(_cubes[i], {y : -100}, _wait, Cubic.easeInOut),
                        BetweenAS3.to(_cubes[i], {x : _ends[i].x}, _wait, Cubic.easeInOut),
                        BetweenAS3.to(_cubes[i], {y : _ends[i].y}, _wait, Cubic.easeInOut),
                        BetweenAS3.to(_cubes[i], {z : _ends[i].z}, _wait, Cubic.easeInOut)
                        ),
                    cap * _wait
                    );
                _last.play();
                left--;
                if(left == 0){
                    cap++;
                    left = Math.min(cap, 8);
                }
            }
        }
        
        override protected function onRenderTick(e : Event = null) : void
        { 
            SphereCamera(camera).move(0.005, 0);
            var w : Number = Math.sin(_t * 0.1) / 2 + 0.5;
            if(_last.isPlaying){
                paint(_face, new ColorHSV(240, 0.9, 0.3 * w + 0.7).value);
            }else{
                paint(_face, new ColorHSV(_u, 0.9, 1.0).value);
                _u += 2;
            }
//            paint(_face, 0x3f << 16 | (uint)(0x3f * (1 - w) + 0xff * w) << 8 | (uint)(0x3f * w + 0xff * (1 - w)));
            
            _t++;
            super.onRenderTick(e);
        }
        
        private function tr(...o : Array) : void
        {
            _tf.appendText(o + "\n");
            _tf.scrollV = _tf.maxScrollV;
        }
    }
}

import org.papervision3d.objects.*;
import org.papervision3d.core.math.*;

class PV3DUtils
{
    public static function rotate(x : Number3D, axis : Number3D, angle : Number) : Number3D
    {
        var nCos:Number    = Math.cos(angle);
        var nSin:Number    = Math.sin(angle);
        var scos:Number    = 1 - nCos;

        var sxy    :Number = axis.x * axis.y * scos;
        var syz    :Number = axis.y * axis.z * scos;
        var sxz    :Number = axis.x * axis.z * scos;
        var sz    :Number = nSin * axis.z;
        var sy    :Number = nSin * axis.y;
        var sx    :Number = nSin * axis.x;

        var nx : Number = (nCos + axis.x * axis.x * scos) * x.x + (-sz + sxy) * x.y + (sy + sxz) * x.z;
        var ny : Number = (sz + sxy) * x.x + (nCos + axis.y * axis.y * scos) * x.y + (-sx + syz) * x.z;
        var nz : Number = (-sy + sxz) * x.x + (sx + syz) * x.y + (nCos + axis.z * axis.z * scos) * x.z;

        x.x = nx; x.y = ny; x.z = nz;
        return x;
    }
    
    public static function rotateMulti(xs : Array, axis : Number3D, angle : Number) : void
    {
        var nCos:Number    = Math.cos(angle);
        var nSin:Number    = Math.sin(angle);
        var scos:Number    = 1 - nCos;

        var sxy    :Number = axis.x * axis.y * scos;
        var syz    :Number = axis.y * axis.z * scos;
        var sxz    :Number = axis.x * axis.z * scos;
        var sz    :Number = nSin * axis.z;
        var sy    :Number = nSin * axis.y;
        var sx    :Number = nSin * axis.x;

        for each(var x : Number3D in xs){
            var nx : Number = (nCos + axis.x * axis.x * scos) * x.x + (-sz + sxy) * x.y + (sy + sxz) * x.z;
            var ny : Number = (sz + sxy) * x.x + (nCos + axis.y * axis.y * scos) * x.y + (-sx + syz) * x.z;
            var nz : Number = (-sy + sxz) * x.x + (sx + syz) * x.y + (nCos + axis.z * axis.z * scos) * x.z;
            x.x = nx; x.y = ny; x.z = nz;
        }
    }
    
    public static function setLookAt(d : DisplayObject3D, front : Number3D, up : Number3D) : void
    {
        var X : Number3D = Number3D.cross(front, up);
        var look : Matrix3D = d.transform;
        look.n11 = X.x; look.n21 = X.y; look.n31 = X.z;
        look.n12 = -up.x; look.n22 = -up.y; look.n32 = -up.z;
        look.n13 = front.x; look.n23 = front.y; look.n33 = front.z;
    }    
}

import org.papervision3d.cameras.*;

class QCamera3D extends Camera3D
{
    public var _up : Number3D; // カメラの上の向きの単位ベクトル
    protected var _front : Number3D;
    private var _prevDir : Number3D;
    
    public function QCamera3D(up : Number3D, front : Number3D= null)
    {
        super();
        _up = null;
        init(up, front);
    }
    
    // prevDirからcurDirへ向ける回転を_upにかけるだけ。カメラ自体に操作はしない
    public function rotate(curDir : Number3D) : void
    {
        if(_prevDir != null){
            var n : Number3D = Number3D.cross(curDir, _prevDir);
//            if(n.moduloSquared > 0.00000001){
            if(n.moduloSquared != 0){
                n.normalize();
                var angle : Number = Math.acos(Number3D.dot(_prevDir, curDir));
                if(_front != null){
                        PV3DUtils.rotate(_front, n, angle);
                }
                   PV3DUtils.rotate(_up, n, angle);
            }
        }
        _prevDir = curDir.clone();
    }
    
    // カメラを_frontのほうへ向ける
    public function head() : void
    {
        if(_front != null){
                var Z : Number3D = _front.clone();
            Z.normalize();
            var X : Number3D = Number3D.cross(Z, _up);
            X.normalize();
            var Y : Number3D = Number3D.cross(Z, X);
            Y.normalize();

            var look : Matrix3D = this.transform;
            look.n11 = X.x*this.scaleX; look.n21 = X.y*this.scaleY; look.n31 = X.z*this.scaleZ;
            look.n12 = -Y.x*this.scaleX; look.n22 = -Y.y*this.scaleY; look.n32 = -Y.z*this.scaleZ;
            look.n13 = Z.x*this.scaleX; look.n23 = Z.y*this.scaleY; look.n33 = Z.z*this.scaleZ;
        }
    }
    
    public function init(up : Number3D = null, front : Number3D = null) : void
    {
        if(up != null){
            _up = up.clone();
            _up.normalize();
        }
        if(front != null){
            _front = front.clone();
            _front.normalize();
        }else{
            _front = null;
        }
        _prevDir = null;
    }
}

// 球面上を動き、球の中心を見るカメラ
class SphereCamera extends QCamera3D
{
    private var _O : Number3D; // 球の中心
    private var _R : Number; // 球の半径
    
    // O : 中心座標
    // R : 半径
    // front : カメラ正面の向きを表す単位ベクトル
    // up : カメラ上の向きを表す単位ベクトル
    public function SphereCamera(O : Number3D, R : Number, front : Number3D, up : Number3D) : void
    {
        super(up, front);
        _O = O;
        _R = R;
        move();
    }
    
    public function move(x : Number = 0, y : Number = 0) : void
    {
        if(x != 0 || y != 0){
        var X : Number3D = Number3D.cross(_up, _front);
        var axis : Number3D = new Number3D(X.x * -y + _up.x * x, X.y * -y + _up.y * x, X.z * -y + _up.z * x);
        var angle : Number = axis.modulo;
        axis.normalize();
        PV3DUtils.rotate(_front, axis, angle);
        PV3DUtils.rotate(_up, axis, angle);
        this.x = _front.x * -_R + _O.x;
        this.y = _front.y * -_R + _O.y;
        this.z = _front.z * -_R + _O.z;
        head();
        }
    }

}

import flash.display.*;
import flash.events.*;

class OperableSphereCamera extends SphereCamera
{
    private var _dx : Number;
    private var _dy : Number;
    private var _stage : DisplayObject;
    private var _prevX : Number = -1;
    private var _prevY : Number = -1;
    private var _down : Boolean = false;

    // O : 中心座標
    // R : 半径
    // front : カメラ正面の向きを表す単位ベクトル
    // up : カメラ上の向きを表す単位ベクトル
    // stage : マウスイベントをlistenするDisplayObject
    // dx : カメラ横への移動角度単位
    // dy : カメラ上への移動角度単位
    public function OperableSphereCamera(O : Number3D, R : Number, front : Number3D, up : Number3D, stage : DisplayObject, dx : Number, dy : Number) : void
    {
      super(O, R, front, up);
      _dx = dx;
      _dy = dy;
      _stage = stage;
      addCallback();
    }
    
    public function addCallback() : void
    {
      _stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      _stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
      _stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }
    
    public function removeCallback() : void
    {
      _stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      _stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
      _stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
    }
    
    private function onMouseDown(e : MouseEvent) : void { _down = true; }
    private function onMouseUp(e : MouseEvent) : void { _down = false; }
    
    private function onEnterFrame(e : Event) : void
    {
      if(_down){
        if(_prevX != -1){
          this.move((_stage.mouseX - _prevX) * _dx, (_stage.mouseY - _prevY) * _dy);
        }
        _prevX = _stage.mouseX;
        _prevY = _stage.mouseY;
      }else{
        _prevX = -1;
        _prevY = -1;
      }
    }
}