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

DisplayObject3D.lookAt()をQuaternion使って実装

Get Adobe Flash player
by uwi 31 Oct 2009
/**
 * Copyright uwi ( http://wonderfl.net/user/uwi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/vqj6
 */

package {
    import flash.display.Sprite;
    import flash.events.Event;
    import org.papervision3d.view.BasicView;
    import org.papervision3d.objects.special.*;
    import org.papervision3d.materials.special.*;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.core.math.*;
    import flash.text.*;
    
    [SWF(backgroundColor="0x000000", frameRate="60")]
    public class FlashTest extends BasicView {
        private var _up : Number3D;
        private var _front : Number3D;
        private var _targ : Number3D;
        
        private var _tf : TextField;
        
        public function FlashTest() {
            super(0, 0, true, false);
            
            _tf = new TextField();
            addChild(_tf);
            _tf.textColor = 0xffffff;
            _tf.width = 465;
            _tf.height = 100;
            
            var pf : ParticleField = new ParticleField(
                new ParticleMaterial(0xffffff, 10, ParticleMaterial.SHAPE_SQUARE),
                500,
                1,
                200, 200, 200);
            scene.addChild(pf);
            camera.z = -70;
            
            _up = new Number3D(0, 1, 0);
            _front = new Number3D(0, 0, 1);
            
            setTarg();
            startRendering();
        }
        
        private function setTarg() : void
        {
            // 目標視線ベクトルを決める
            var t : Number = Math.random() * Math.PI * 2;
            var u : Number = Math.random() * Math.PI;
            _targ = new Number3D(
                Math.cos(t) * Math.cos(u),
                Math.sin(t) * Math.cos(u),
                Math.sin(u)
                );
                
            // 差をとって回転用クォータニオンを生成
            var n : Number3D = Number3D.cross(_front, _targ);
            n.normalize();
            var angle : Number = Math.acos(Number3D.dot(_front, _targ));
            _q = Quaternion.createFromAxisAngle(n.x, n.y, n.z, 0.01);
            _qc = Quaternion.conjugate(_q);
        }
        
        private var _q : Quaternion;
        private var _qc : Quaternion;
        
        // クォータニオンのベクトルへの適用
        private function applyQuaternion(src : Number3D, q : Quaternion, qc : Quaternion) : Number3D
        {
            var qSrc : Quaternion = new Quaternion(src.x, src.y, src.z, 0);
            var qDst : Quaternion = Quaternion.multiply(qc, qSrc);
            qDst = Quaternion.multiply(qDst, q);
            return new Number3D(qDst.x, qDst.y, qDst.z);
        }
        
        override protected function onRenderTick(e : Event = null) : void
        {
//            _tf.text = "" + _q + "\n" + camera.scaleZ;
            
            // 視線とカメラの上のベクトルを回転
            _front = applyQuaternion(_front, _q, _qc);
            _up = applyQuaternion(_up, _q, _qc);
            
            // 行列をつくってカメラに適用
            var xAxis : Number3D = Number3D.cross(_front, _up);
            xAxis.normalize();
            var look : Matrix3D = new Matrix3D();
            look.n11 = xAxis.x * camera.scaleX;
            look.n21 = xAxis.y * camera.scaleX;
            look.n31 = xAxis.z * camera.scaleX;
            look.n12 = -_up.x * camera.scaleY;
            look.n22 = -_up.y * camera.scaleY;
            look.n32 = -_up.z * camera.scaleY;
            look.n13 = _front.x * camera.scaleZ;
            look.n23 = _front.y * camera.scaleZ;
            look.n33 = _front.z * camera.scaleZ;
            camera.copyTransform(look);
            
            // 方向転換
            if(Number3D.dot(_front, _targ) < 0.03){
                setTarg();
            }
            
            super.onRenderTick(e);
        }
    }
}