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

unproject 2D point

turn mouse coordinates to 3D world coordinates -- the painful way
Get Adobe Flash player
by mutantleg 23 Oct 2012

    Tags

    3D
    Embed
/**
 * Copyright mutantleg ( http://wonderfl.net/user/mutantleg )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/7nUP
 */

package {
    import flash.geom.Point;
    import flash.text.TextField;
    import flash.geom.Matrix3D;
    import flash.display.BlendMode;
    import flash.display.BitmapData;
    import flash.events.KeyboardEvent;
    import flash.events.Event;
    //import flash.media.Camera;
  
    //http://alternativaplatform.com/en/docs/7.7.0/index.html
    
    import alternativ7.engine3d.containers.ConflictContainer;
    import alternativ7.engine3d.containers.BSPContainer;
    import alternativ7.engine3d.core.Object3DContainer;
    import alternativ7.engine3d.core.Camera3D;
    import alternativ7.engine3d.core.EllipsoidCollider;
    import alternativ7.engine3d.objects.Mesh;
    import alternativ7.engine3d.primitives.Plane;
    import alternativ7.engine3d.primitives.Box;
    import alternativ7.engine3d.primitives.Sphere;
    import alternativ7.engine3d.primitives.GeoSphere;
    import alternativ7.engine3d.core.View;
     import alternativ7.engine3d.materials.Material;
    import alternativ7.engine3d.materials.FillMaterial;
    import alternativ7.engine3d.materials.TextureMaterial;
    import alternativ7.engine3d.materials.NormalMapMaterial;
    import alternativ7.engine3d.materials.FlatShadingMaterial;
    import alternativ7.engine3d.materials.VertexLightMaterial;
    import alternativ7.engine3d.materials.AverageLightMaterial;
    import alternativ7.engine3d.materials.SphericalEnvironmentMaterial;
    import alternativ7.types.Texture;
    import alternativ7.types.Point3D;
    import alternativ7.engine3d.lights.AmbientLight;
    import alternativ7.engine3d.lights.DirectionalLight;
    import alternativ7.engine3d.lights.OmniLight;
    import alternativ7.engine3d.lights.SpotLight;
    import flash.display.Sprite;
    
    public class FlashTest extends Sprite {
        
        public var cam:Camera3D;
        public var cont:Object3DContainer = new Object3DContainer();
        public var gBox:Box;
        public var targ:Sprite;
        public var ori:cQuat;
        public var mat:Matrix3D;
        public var camx:Number = 0;
        public var camy:Number = 0;
        public var camz:Number = 0;
        public var debText:TextField;
        public var myFrust:cFrustum;
        
        public var vecLine:Vector.<Mesh>;
        
        public function FlashTest() {
            // write as3 code here..
               cam = new Camera3D();
                cam.view = new View(400,400); 
                ///cam.z = -1000;
                
                //cam.fov = (90+30)*(3.1415*180.0);
                
                myFrust = new cFrustum();
                myFrust.setPersp( 70, 1,0.1, 3000);
                
                
                ori = new cQuat();
                mat = new Matrix3D();
                
                camy = -900;
                camz = -600;
                ori.rotPitch(-0.4);
                
               addChild(cam.view);
                cont.addChild(cam);
                
                var bm:BitmapData;
                bm = new BitmapData(64,64,false,0);
                bm.noise(123213,0,16,3,true);
                
                var p:Plane;
                
                p = new Plane(1000, 1000, 8, 8);
                p.setMaterialToAllFaces( new TextureMaterial( bm ) );
                p.rotationX = 1.57;
                p.y = 200+10;
                cont.addChild(p);
                
                bm = new BitmapData(64,64,false,0);
                bm.noise(123123);
               
                
                var i:int;
                var m:Mesh;
                vecLine = new Vector.<Mesh>;
                for (i = 0; i < 10; i++)
                {
                    m = new Box(20,20,20,1,1,1);
                    m.setMaterialToAllFaces(new FillMaterial(0xFF0000,0.5));
                    vecLine.push(m);
                    cont.addChild(m);
                }//nexti
                
                
                var box:Box;
                box = new Box(60,60,60,1,1,1);
                //box.x = 400;
               // box.setMaterialToAllFaces( new FillMaterial(0) );
                box.setMaterialToAllFaces( new TextureMaterial( bm) );
               //box.setMaterialToAllFaces( new VertexLightMaterial( bm ) );
               //box.setMaterialToAllFaces( new FlatShadingMaterial( bm ) );
               
                  box.calculateVerticesNormals();
                  cont.addChild(box);
                  gBox = box;
                  
                  
                 targ = new Sprite();
                 targ.graphics.clear();
                 targ.graphics.lineStyle(2,0);
                 targ.graphics.drawCircle(0,0,8);
                 addChild(targ);
                  
                  debText = new TextField();
                  debText.text = "debug";
                  debText.width = 400;
                  addChild(debText);
                  
                  stage.addEventListener(Event.ENTER_FRAME, onEnter);  
                  stage.addEventListener(KeyboardEvent.KEY_DOWN, kdown);
                  stage.addEventListener(KeyboardEvent.KEY_UP, kup);    
               
               
        }//ctor
        
        public var proj:Matrix3D = new Matrix3D();
        public var look:Matrix3D = new Matrix3D();
        
        public var testOri:cQuat = new cQuat();
        
        public function onEnter(e:Event):void
        {
          //  var m:Vector.<Number>;
            
            //ref
         //http://www.dakmm.com/?p=272
           if (cKeyMan.isKeyDown(39) ) { ori.rotYaw(0.1);}
            if (cKeyMan.isKeyDown(37) ) { ori.rotYaw(-0.1);}
           // if (cKeyMan.isKeyDown(38) ) { cam.y += 20;}
           // if (cKeyMan.isKeyDown(40) ) { cam.y -= 20;}
         
            
            targ.x = stage.mouseX;
            targ.y = stage.mouseY;
           /*
           var dx:Number, dy:Number;
           
           dx = ((stage.mouseX / 500)-0.5)*2;
           dy = ((stage.mouseY / 500)-0.5)*2;
           //dx = stage.mouseX/500;
           //dy = stage.mouseY/500;
           //dy *= -1;
           
          // dx = 0;
          // dy = 0;
           
           debText.text = "dx " +dx + " dy " + dy;
            
            m = proj.rawData;
            setProjectionMatrix(m, 90,1,1,2000);
            proj.rawData = m;
            proj.invert();
     
         
            m = look.rawData;
            setLookAtMatrix(m, camx,camy,camz,ori.x,ori.y,ori.z, ori.w);
            look.rawData = m;
            look.invert();
            
            var far:Number = 1;
            
            m = proj.rawData;
            
            mx = dx * m[0] + dy * m[4] + far *-1* m[8] + m[12];
            my = dx * m[1] + dy * m[5] + far *-1* m[9] + m[13];
            mz = dx * m[2] + dy * m[6] + far *-1* m[10] + m[14];
            mw = dx * m[3] + dy * m[7] + far *-1* m[11] + m[15];
            
            
            m = look.rawData;
            
            kx = mx * m[0] + my * m[4] + mz * m[8] + m[12];
            ky = mx * m[1] + my * m[5] + mz * m[9] + m[13];
            kz = mx * m[2] + my * m[6] + mz * m[10] + m[14];
            kw = mx * m[3] + my * m[7] + mz * m[11] + m[15];
            
            kx *= kw;
             ky *= kw;
            kz *= kw;
            
            debText.text = "kx " +kx + " ky " + ky + " kz " + kz;
             gBox.x = kx;
            gBox.y = ky;
            gBox.z = kz;
            
            far = 1000;
             m = proj.rawData;
            
            mx = dx*far *m[0] + dy*far * m[4] + far*1 * m[8] + m[12];
            my = dx*far * m[1] + dy*far * m[5] + far*1 * m[9] + m[13];
            mz = dx*far * m[2] + dy*far * m[6] + far*1 * m[10] + m[14];
            mw = dx*far * m[3] + dy*far * m[7] + far*1 * m[11] + m[15];
            
              m = look.rawData;
            
            tx = mx * m[0] + my * m[4] + mz * m[8] + m[12];
            ty = mx * m[1] + my * m[5] + mz * m[9] + m[13];
            tz = mx * m[2] + my * m[6] + mz * m[10] + m[14];
            tw = mx * m[3] + my * m[7] + mz * m[11] + m[15];
            
            tx *= tw;
            ty *= tw;
            tz *= tw;
            
            
          //  gBox.rotationY += 0.1;
            
            var tx:Number, ty:Number, tz:Number, tw:Number;
            var mx:Number, my:Number, mz:Number, mw:Number;
            var kx:Number, ky:Number, kz:Number, kw:Number;z
            var t:Number;
            
            mx = 0; my = -100; mz = 0;
            kx = 0; ky = 500; kz = 0;
            
            t = linePlaneTest(kx, ky,kz, tx,ty,tz, 0,200,0, 0,-1,0 );
            
            gBox.x = kx + (tx - kx) * t;
            gBox.y = ky + (ty - ky) * t;
            gBox.z = kz + (tz - kz) * t;
           */
           // camz = -1000;
           
           var umx:Number;
           var umy:Number;
           var t:Number;
           var kx:Number, ky:Number, kz:Number;
            
            //alternativa camera fov is by default is 1.57 .. aka 90 ... which is actually 60 (what in the flying f
           umx = ((stage.mouseX / 400)-0.5)*2;//*1.46;
           umy = ((stage.mouseY / 400)-0.5)*2;//*1.46;
            
            
            myFrust.setPoint(camx, camy, camz, ori, umx, umy);
           // myFrust.setPoint(0, -200, 0, testOri, umx, umy);      
            
            t = linePlaneTest(myFrust.sax, myFrust.say, myFrust.saz, 
            myFrust.sbx, myFrust.sby, myFrust.sbz, 0,200,0, 0,-1,0 );
            
            debText.text = "t " + t;
            debText.appendText("\n mx " +stage.mouseX + " my " + stage.mouseY);
            debText.appendText("\n umx " + umx + "\n umy " +umy);
            
            kx = myFrust.sax + (myFrust.sbx - myFrust.sax) * t;
            ky = myFrust.say + (myFrust.sby - myFrust.say) * t;
            kz = myFrust.saz + (myFrust.sbz - myFrust.saz) * t;
            
            var i:Number;
            var m:Mesh;
            for (i = 0; i < 10; i++)
            {
                m = vecLine[i];
                m.x = myFrust.sax + (myFrust.sbx - myFrust.sax) * (i*0.1);
                m.y = myFrust.say + (myFrust.sby - myFrust.say) * (i*0.1);
                m.z = myFrust.saz + (myFrust.sbz - myFrust.saz) * (i*0.1);
                
            }//nexti
            
            gBox.x = kx;
            gBox.y = ky;
            gBox.z = kz;
            
          //  res = View.get3DCoords(p, 40, null);
            
            /*
            gBox.x = res.x;
            gBox.y = res.y;
            gBox.z = res.z;
            */
            ori.setMatrix(mat);
            mat.appendTranslation(camx,camy,camz);
            cam.matrix = mat;
            
             cam.render();
             
        }//onenter
        
       // public var res:Point3D;
      //  public var p:Point;
        
        public function kdown(e:KeyboardEvent):void
        {
         cKeyMan.setKey(e.keyCode, true);   
        }//kdown
        
        public function kup(e:KeyboardEvent):void
        {
          cKeyMan.setKey(e.keyCode, false);  
        }//kup
        
        public function linePlaneTest(
        ax:Number, ay:Number, az:Number,
        bx:Number, by:Number, bz:Number,
        px:Number, py:Number, pz:Number,
        nx:Number, ny:Number, nz:Number):Number
        {
            var dx:Number, dy:Number, dz:Number;
            var vx:Number, vy:Number, vz:Number;
            var ndotv:Number;
            
            vx = bx - ax;
            vy = by - ay;
            vz = bz - az;
            
            dx = px - ax;
            dy = py - ay;
            dz = pz - az;
            
            ndotv = (vx *nx) + (vy*ny)+(vz*nz);
            if (ndotv == 0) {return -99999;} //parallel -- no inter
            
            return ((nx*dx)+(ny*dy)+(nz*dz)) / ndotv; 
            
        }//lineplane
        
        
        public function setProjectionMatrix(
        vec:Vector.<Number>, 
        fovdeg:Number = 90.0, 
        aspect:Number=1.0, nearp:Number = 1.0, farp:Number=1000.0):void
        {
            var f:Number;
            var i:int;

            for (i = 0; i < 16; i++) { vec[i] = 0.0;  } 

            f = 1.0 / Math.tan( (fovdeg * (3.1415 / 180.0)) * 0.5 );

            if (nearp == 0) { nearp = 0.0001; }
            if (farp == 0) { farp = 0.0001; }

            vec[0] = f / aspect;
            vec[5] = f;
            vec[10] = (farp + nearp) / (nearp - farp);
            vec[14] = (2.0 * farp * nearp) / (nearp - farp);
            vec[11] = -1.0;
            vec[15] = 0.0;
        }//projmatrix
        
        public function setLookAtMatrix(
        vec:Vector.<Number>, 
        cx:Number, cy:Number, cz:Number,  
        qx:Number, qy:Number, qz:Number, qw:Number):void
        {
            var forwx:Number;     var forwy:Number;    var forwz:Number;
            var sidex:Number;     var sidey:Number;     var sidez:Number;
            var upx:Number;     var upy:Number;     var upz:Number;
            var i:int;

            for (i = 0; i < 16; i++) { vec[i] = 0.0;  } 
   
            forwx = 2.0 * ( qx*qz + qy*qw );
            forwy = 2.0 * ( qy*qz - qx*qw );
            forwz = 1.0 - 2.0 * ( qx*qx + qy*qy );
            upx = 2.0 * ( qx*qy - qz*qw );
            upy = 1.0 - 2.0 * ( qx*qx + qz*qz );
            upz = 2.0 * ( qy * qz + qx * qw );
            sidex = 1.0 - 2.0 * ( qy*qy + qz*qz );
            sidey = 2.0 * ( qx*qy + qz*qw );
            sidez = 2.0 * ( qx * qz - qy * qw );

            vec[0] = vec[5] = vec[10] = vec[15] = 1.0; 
            vec[0] = sidex;    vec[4] = sidey;    vec[8] = sidez;
            vec[1] = upx;        vec[5] = upy;        vec[9] = upz;
            vec[2] = -forwx;    vec[6] = -forwy;    vec[10] = -forwz;

            vec[12] = (sidex *-cx) + (sidey * -cy) + (sidez * -cz);
            vec[13] = (upx *-cx) + (upy * -cy) + (upz * -cz);
            vec[14] = (-forwx *-cx) + (-forwy * -cy) + (-forwz * -cz);

        }//setlookat
        
        
    }//flashtest
}
import flash.geom.Matrix3D;//package


internal class cKeyMan
   {
       public function cKeyMan() {}//ctor (unused)
       
       public static var vecKey:Vector.<Boolean> = new Vector.<Boolean>(512,true);
       
       public static function setKey(k:int, b:Boolean):void
       {
           if (k < 0) return;
           if (k >= 512) return;
           vecKey[k] = b;
       }//setkey
       
       public static function isKeyDown(k:int):Boolean
       {
           if  (k < 0) return false;
           if (k >= 512) return false;
           return vecKey[k];
       }//iskey
       
   }//keyman 
    
    
 
internal class cQuat
{
    
    public var x:Number = 0;
    public var y:Number = 0;
    public var z:Number = 0;
    public var w:Number = 1;
    
    public function cQuat()
    {}//ctor
    
    public function reset():void
    { x = 0; y = 0; z = 0; w = 1; }
    
    public function copyQuat(q:cQuat):void
    { x = q.x; y = q.y; z = q.z; w = q.w; }
    
    public function invert():void
    { x = -x; y = -y; z = -z; }
    
    public function normalise():void
    {
        var mag:Number;
        
        mag = x*x + y*y + z*z + w*w;
        if (mag == 1.0) {return;}
        if (mag == 0.0) {x=0;y=0;z=0;w=1; return;}
        
        mag = 1.0 / Math.sqrt(mag);
        
        x*= mag;
        y*= mag;
        z*= mag;
        w*= mag;
        
    }//normal
    
    //multiply with other quaternion
    public function mul(b:cQuat):void
    {
            var tx:Number;
            var ty:Number;
            var tz:Number;
            var tw:Number;
            
            tx =    (w*b.x + x*b.w + y*b.z - z*b.y),
            ty =    (w*b.y + y*b.w + z*b.x - x*b.z),
            tz =    (w*b.z + z*b.w + x*b.y - y*b.x),
            tw =    (w*b.w - x*b.x - y*b.y - z*b.z);

            x = tx;
            y = ty;
            z = tz;
            w = tw; 
    }//mul
    
    public function mulq(px:Number, py:Number, pz:Number, pw:Number):void
    {
            var tx:Number;
            var ty:Number;
            var tz:Number;
            var tw:Number;
            
            tx =    (w*px + x*pw + y*pz - z*py),
            ty =    (w*py + y*pw + z*px - x*pz),
            tz =    (w*pz + z*pw + x*py - y*px),
            tw =    (w*pw - x*px - y*py - z*pz);

            x = tx;
            y = ty;
            z = tz;
            w = tw; 
    }//mulq
    
    //rotate pitch by angle (in radian)
    public function rotPitch(ang:Number):void
    {
        ang *= 0.5;        
        mulq(Math.sin(ang),0,0, Math.cos(ang));
        normalise();
     }//rotpitch
    
    public function rotYaw(ang:Number):void
    {
        ang *= 0.5;
        mulq(0,Math.sin(ang),0, Math.cos(ang));
        normalise();
     }//rotyaw
    
    public function rotRoll(ang:Number):void
    {
        ang *= 0.5;
        mulq(0,0,Math.sin(ang), Math.cos(ang));
        normalise();
     }//rotpitch


    public static var tempVec:Vector.<Number> = new Vector.<Number>(16,true);
    public function setMatrix(m:Matrix3D):void
    {
       var xx:Number      = x * x;
       var xy:Number      = x * y;
       var xz:Number      = x * z;
       var xw:Number      = x * w;

       var yy:Number      = y * y;
       var yz:Number      = y * z;
       var yw:Number      = y * w;

       var zz:Number      = z * z;
       var zw:Number      = z * w;
        
            tempVec[3]  = tempVec[7] = tempVec[11] = tempVec[12] = tempVec[13] = tempVec[14] = 0.0;
            tempVec[15] = 1.0;

            
            tempVec[0]  = 1.0 - 2.0 * ( yy + zz );
            tempVec[4]  =     2.0 * ( xy - zw );
            tempVec[8]  =     2.0 * ( xz + yw );

            tempVec[1]  =  2.0 * ( xy + zw ) ;
            tempVec[5]  = 1.0 - 2.0 * ( xx + zz ) ;
            tempVec[9]  =  2.0 * ( yz - xw ) ;

            tempVec[2]  =     2.0 * ( xz - yw );
            tempVec[6]  =     2.0 * ( yz + xw );
            tempVec[10] = 1.0 - 2.0 * ( xx + yy );
            
      m.rawData = tempVec;
        
    }//setmatrix
    
        public function getSideVx():Number
        { return 1.0 - 2.0 * ( y * y + z * z ); }
        
        public function getSideVy():Number
        { return 2.0 * ( x * y + z * w ); }
        
        public function getSideVz():Number
        { return  2.0 * ( x * z - y * w ); }

        public function getUpVx():Number
        { return 2.0 * ( x*y - z*w ); }

        public function getUpVy():Number
        { return 1.0 - 2.0 * ( x*x + z*z ); }
        
        public function getUpVz():Number
        { return 2.0 * ( y*z + x*w ); }

        public function getFrontVx():Number
        {    return  2.0 * ( x*z + y*w ); }
        
        public function getFrontVy():Number
        {   return  2.0 * ( y*z - x*w );     }
        
        public function getFrontVz():Number
        {    return  1.0 - 2.0 * ( x*x + y*y );  }

}//cquat   
    
    
    
internal class cFrustum
{
    public function cFrustum()
    {}//ctor
    
    public var nearWidth:Number, nearHeight:Number;
    public var farWidth:Number, farHeight:Number;

    public var fov:Number;
    public var aspect:Number;
    public var nearDist:Number, farDist:Number;
    
    public function setPersp(fov_:Number= 90, aspect_:Number=1.33, nearDist_:Number=1,  farDist_:Number=300):void
    {
        
        
        fov = fov_;
        aspect = aspect_;
        nearDist = nearDist_;
        farDist = farDist_;
    
        var tang:Number;
        fov_ *= 3.1415 / 180.0 //torad
        tang = Math.tan(fov_ * 0.5);
        
        nearHeight = nearDist * tang;
        nearWidth = nearHeight * aspect;

        farHeight = farDist * tang;
        farWidth = farHeight * aspect;
    
    }//setpersp
    
    public var sax:Number = 0;
    public var say:Number = 0;
    public var saz:Number = 0;
    public var sbx:Number = 0;
    public var sby:Number = 0;
    public var sbz:Number = 0;


    
    //m  -0.5 - 0.5
    public function setPoint(cx:Number, cy:Number, cz:Number, cq:cQuat, umx:Number, umy:Number):void
    {
        var fx:Number, fy:Number, fz:Number;
        var sx:Number, sy:Number, sz:Number;
        var ux:Number, uy:Number, uz:Number;
        var frontx:Number, fronty:Number, frontz:Number;
        var nearx:Number, neary:Number, nearz:Number;
        var farupx:Number, farupy:Number, farupz:Number;
        var farsidex:Number, farsidey:Number, farsidez:Number;
        var nearupx:Number, nearupy:Number, nearupz:Number;
        var nearsidex:Number, nearsidey:Number, nearsidez:Number;
        var nh:Number, nw:Number, fh:Number, fw:Number; 
        
        fx = cq.getFrontVx();
        fy = cq.getFrontVy();
        fz = cq.getFrontVz();
        sx = cq.getSideVx();
        sy = cq.getSideVy();
        sz = cq.getSideVz();
        ux = cq.getUpVx();
        uy = cq.getUpVy();
        uz = cq.getUpVz();   
        
        nh = nearHeight;
        nw = nearWidth;
        fh = farHeight;
        fw = farWidth;
        
        farupx = ux * fh;
        farupy = uy * fh;
        farupz = uz * fh;
        
        farsidex = sx * fw;
        farsidey = sy * fw;
        farsidez = sz * fw;
        
        nearupx = ux * nh;
        nearupy = uy * nh;
        nearupz = uz * nh;
        
        nearsidex = sx * nw;
        nearsidey = sy * nw;
        nearsidez = sz * nw;

        
        frontx = cx + fx * farDist;
        fronty = cy + fy * farDist;
        frontz = cz + fz * farDist;
       
            sbx = frontx + (farupx * umy) + (farsidex * umx);
            sby = fronty + (farupy * umy) + (farsidey * umx);
            sbz = frontz + (farupz * umy) + (farsidez * umx);
            
       
        nearx = cx + fx * nearDist; 
        neary = cy + fy * nearDist; 
        nearz = cz + fz * nearDist; 
        
            sax = nearx + (nearupx * umy) + (nearsidex * umx);
            say = neary + (nearupy * umy) + (nearsidey * umx);
            saz = nearz + (nearupz * umy) + (nearsidez * umx);
    }//setpoint
    
    
}//cfrust