flash on 2013-7-11

by mutantleg
♥0 | Line 507 | Modified 2013-07-11 17:41:41 | MIT License
play

ActionScript3 source code

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

package {
    import flash.text.TextField;
    import flash.events.Event;
    import flash.display.Sprite;
    public class FlashTest extends Sprite {
        public function FlashTest() {
            

            frust.setPerspective(90, 1, 1, 500);
            frust.setPoints(pos, ori, 0,0);      
            
            
            
              vecCutter[0].setPlane(frust.pa.x, frust.pa.y, frust.pa.z,  frust.norma.x, frust.norma.y, frust.norma.z);
              vecCutter[1].setPlane(frust.pb.x, frust.pb.y, frust.pb.z,  frust.normb.x, frust.normb.y, frust.normb.z);
              vecCutter[2].setPlane(frust.pc.x, frust.pc.y, frust.pc.z,  frust.normc.x, frust.normc.y, frust.normc.z);
              vecCutter[3].setPlane(frust.pd.x, frust.pd.y, frust.pd.z,  frust.normd.x, frust.normd.y, frust.normd.z);
              vecCutter[4].setPlane(frust.pe.x, frust.pe.y, frust.pe.z,  frust.norme.x, frust.norme.y, frust.norme.z);
              vecCutter[5].setPlane(frust.pf.x, frust.pf.y, frust.pf.z,  frust.normf.x, frust.normf.y, frust.normf.z);
            
              
              deb = new TextField();
              deb.mouseEnabled = false;
              deb.width = 320;
              deb.height = 240;
              addChild(deb);
            
            
            stage.addEventListener(Event.ENTER_FRAME, onEnter);
        }//ctor
        
        
           public var ang:Number = 0;
        
           public var myTri:xTri = new xTri();
        
           public var deb:TextField;

          public var mang:Number = 0;
        
        public function onEnter(e:Event):void
        {    
        
            graphics.clear();
            graphics.lineStyle(2, 0);
            
            deb.text = "";
            
            mang += 0.01;
            pos.z = -300 + (Math.cos(mang)*Math.sin(mang)) * 256;
            
            
            
             frust.setPerspective(90, 1, 1, 1500);
            frust.setPoints(pos, ori, 0,0);      
            
              vecCutter[0].setPlane(frust.pa.x, frust.pa.y, frust.pa.z,  frust.norma.x, frust.norma.y, frust.norma.z);
              vecCutter[1].setPlane(frust.pb.x, frust.pb.y, frust.pb.z,  frust.normb.x, frust.normb.y, frust.normb.z);
              vecCutter[2].setPlane(frust.pc.x, frust.pc.y, frust.pc.z,  frust.normc.x, frust.normc.y, frust.normc.z);
              vecCutter[3].setPlane(frust.pd.x, frust.pd.y, frust.pd.z,  frust.normd.x, frust.normd.y, frust.normd.z);
              vecCutter[4].setPlane(frust.pe.x, frust.pe.y, frust.pe.z,  frust.norme.x, frust.norme.y, frust.norme.z);
              vecCutter[5].setPlane(frust.pf.x, frust.pf.y, frust.pf.z,  frust.normf.x, frust.normf.y, frust.normf.z);
            
            
            setProjMat(proj, 90, 1, 1, 1500);
            setViewMat(view, pos.x, pos.y, pos.z, ori.x, ori.y, ori.z, ori.w);
            
             multMatrix(proj, view, projview);

            
            ang += 0.0003;

              myTri.a.setValue(200+Math.cos(ang-1.57)*200,200+Math.sin(ang-1.57)*200,100);
             myTri.b.setValue(200+Math.cos(ang)*200,200+Math.sin(ang)*200,100);
             myTri.c.setValue(200+Math.cos(ang+1.57)*200,200+Math.sin(ang+1.57)*200,100);
          
            
           // renderTri(myTri);
            drawCut(myTri, 0);
            
        }//onenter
        
          public var pos:xVec = new xVec();
          public var ori:xQuat = new xQuat();
          public var frust:xFrustum = new xFrustum();
        
          public var vecCutter:Vector.<xCutter> =  Vector.<xCutter>([new xCutter(), new xCutter(), new xCutter(), new xCutter(), new xCutter(), new xCutter()]);

          public var projview:Vector.<Number> = new Vector.<Number>(16, false);
          public var proj:Vector.<Number> = new Vector.<Number>(16, false);
          public var view:Vector.<Number> = new Vector.<Number>(16, false);
          

        public function drawCut(tri:xTri, d:int=0):void
        {
          var cut:xCutter;
          var num:int;
          
          if (d >= 6) { renderTri(tri); return; }
          
          cut = vecCutter[d];
          num = cut.cutTri(tri);
          if (num < 0) {  return; }
          if (num == 0) { drawCut(tri, d+1); return; }
          
          drawCut(cut.ret1, d+1);
          
          if (num > 1) { drawCut(cut.ret2, d+1);}
          
        }//drawtri
        
        public function renderTri(tri:xTri):void
        {
            //deb.appendText(" tri ");
            
            var mat:Vector.<Number>;
            var w:Number;
            var vx:Number;
            var vy:Number;
            var vz:Number;
            var sx:Number;
            var sy:Number;
            var sx2:Number;
            var sy2:Number;
            var sx3:Number;
            var sy3:Number;
            
            mat = projview;
            
            vx = tri.a.cx;
            vy = tri.a.cy;
            vz = tri.a.cz;
            
            sx = vx * mat[0] + vy * mat[4] + vz * mat[8] + mat[12];
            sy = vx * mat[1] + vy * mat[5] + vz * mat[9] + mat[13];
             w = vx * mat[3] + vy * mat[7] + vz * mat[11] + mat[15];
        
                if (w == 0) { w = 0.00001;} 
        
               sx /= w;
               sy /= w;

               
            
            vx = tri.b.cx;
            vy = tri.b.cy;
            vz = tri.b.cz;
            
            sx2 = vx * mat[0] + vy * mat[4] + vz * mat[8] + mat[12];
            sy2 = vx * mat[1] + vy * mat[5] + vz * mat[9] + mat[13];
             w = vx * mat[3] + vy * mat[7] + vz * mat[11] + mat[15];
        
                if (w == 0) { w = 0.00001;} 
        
               sx2 /= w;
               sy2 /= w;

            
            vx = tri.c.cx;
            vy = tri.c.cy;
            vz = tri.c.cz;
            
            sx3 = vx * mat[0] + vy * mat[4] + vz * mat[8] + mat[12];
            sy3 = vx * mat[1] + vy * mat[5] + vz * mat[9] + mat[13];
             w = vx * mat[3] + vy * mat[7] + vz * mat[11] + mat[15];
        
                if (w == 0) { w = 0.00001;} 
        
               sx3 /= w;
               sy3 /= w;

            
            sx *= 465;
            sy *= 465;
            sx2 *= 465;
            sy2 *= 465;
            sx3 *= 465;
            sy3 *= 465;
               
            
            graphics.beginFill(0, 0.5);
                graphics.moveTo(sx, sy);
                graphics.lineTo(sx2, sy2);
                graphics.lineTo(sx3, sy3);
                graphics.lineTo(sx, sy);
               
            graphics.endFill();
            
            /*
            graphics.beginFill(0, 0.5);
            graphics.moveTo(tri.a.cx+200, tri.a.cy+200);
            graphics.lineTo(tri.b.cx+200, tri.b.cy+200);
            graphics.lineTo(tri.c.cx+200, tri.c.cy+200);
            graphics.lineTo(tri.a.cx+200, tri.a.cy+200);
            graphics.endFill();
           */ 
        }//rendertri
                
        
        
        
        public function setProjMat(vec:Vector.<Number>, //m:Matrix3D,
        fovdeg:Number = 60.0, 
            aspect:Number=1.0, nearp:Number = 1.0, farp:Number=1000.0):void
        {
            //var vec:Vector.<Number> = m.rawData;
            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;
            
            //    m.rawData = vec;
        }//projmatrix
        
        
        public function setViewMat(vec:Vector.<Number>, //m:Matrix3D,
            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;
            //var vec:Vector.<Number> = m.rawData;
            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);
            
            //m.rawData = vec;


        }//setlookat


        //only works of 4x4 matrices
        public function multMatrix(a:Vector.<Number>, b:Vector.<Number>, r:Vector.<Number>):void
        {
            var i:int;
            
            for (i = 0; i < 16; i += 4)
            {
                r[i] =     a[0] * b[i] + a[4] * b[i + 1] + a[8] * b[i + 2] + a[12] * b[i + 3];
                r[i + 1] = a[1] * b[i] + a[5] * b[i + 1] + a[9] * b[i + 2] + a[13] * b[i + 3];
                r[i + 2] = a[2] * b[i] + a[6] * b[i + 1] + a[10] * b[i + 2] + a[14] * b[i + 3];
                r[i + 3] = a[3] * b[i] + a[7] * b[i + 1] + a[11] * b[i + 2] + a[15] * b[i + 3];
            }//nexti
        }//multmat

    }//classend
}





internal class xVert
{
  public var cx:Number = 0;
  public var cy:Number = 0;
  public var cz:Number = 0;
  
  public function copyVert(b:xVert):void  {     cx = b.cx; cy = b.cy; cz = b.cz;  }
  
  public function setValue(vx:Number, vy:Number, vz:Number):void
  { cx = vx; cy = vy; cz = vz;}
  
}//xvert

internal class xTri
{
  public var a:xVert = new xVert();
  public var b:xVert = new xVert();
  public var c:xVert = new xVert();
  
}//xtri

internal class xCutter
{

public var ret1:xTri = new xTri();
public var ret2:xTri = new xTri();

public var num:int = 0;

public var cx:Number = 0;
public var cy:Number = 0;
public var cz:Number = 0;

public var cnx:Number = 0;
public var cny:Number = 0;
public var cnz:Number = 0;


public function setPlane(x_:Number, y_:Number, z_:Number, nx_:Number, ny_:Number, nz_:Number):void
{
    cx = x_;
    cy = y_;
    cz = z_;
    cnx = nx_;
    cny = ny_;
    cnz = nz_;
    
}//setplane

public function isFront(tri:xTri):int
{
    var ad:Number; var bd:Number; var cd:Number;
  
    ad = (tri.a.cx - cx) *cnx +  (tri.a.cy - cy) *cny +(tri.a.cz - cz) *cnz
    bd = (tri.b.cx - cx) *cnx +  (tri.b.cy - cy) *cny +(tri.b.cz - cz) *cnz  
    cd = (tri.c.cx - cx) *cnx +  (tri.c.cy - cy) *cny +(tri.c.cz - cz) *cnz
  
    if (ad > 0 && bd > 0 && cd > 0) { return 1; } //front of plane
    if (ad < 0 && bd < 0 && cd < 0) { return -1; } //behind plane
    return 0; //intersect    
}//isfront

public function cutTri(tri:xTri):int
{
  num = cutTriPlane(tri, cx, cy,cz, cnx, cny, cnz);
  return num;
}//cut


public static var tempOut:Vector.<xVert> = Vector.<xVert>([new xVert(), new xVert(), new xVert(), new xVert()]);

    public function cutTriPlane(tri:xTri,
    px:Number, py:Number, pz:Number,
    nx:Number, ny:Number, nz:Number):int
    {
      var vecOut:Vector.<xVert>;
      var it:int;
      var i:int;
      var ad:Number; var bd:Number; var cd:Number;
      var t:Number;
      var va:xVert; var vs:xVert;
      var da:Number; var ds:Number;
      var dw:xVert;
      
      vecOut = tempOut;
      
      
        ad = (tri.a.cx - px) *nx +  (tri.a.cy - py) *ny +(tri.a.cz - pz) *nz
        bd = (tri.b.cx - px) *nx +  (tri.b.cy - py) *ny +(tri.b.cz - pz) *nz
        cd = (tri.c.cx - px) *nx +  (tri.c.cy - py) *ny +(tri.c.cz - pz) *nz
      
        if (ad > 0 && bd > 0 && cd > 0) { return 0; } //front of plane
      
    
      it = 0;
    
      //todo -- unroll later (and by unroll i mean no loop really needed here)
      for (i = 0; i < 3; i++)
      {
        if (i == 0) 
        {
          va = tri.a;      vs = tri.c;      da = ad;      ds = cd;
        
        } else if (i == 1)
        {
          va = tri.b;      vs = tri.a;      da = bd;      ds = ad;
        
        } else 
        {
          va = tri.c;      vs = tri.b;      da = cd;      ds = bd;
        }
      
      
            if (da > 0 && ds > 0)
            {
              vecOut[it].copyVert(va);
              it += 1;
            }
            else if (da > 0 || ds > 0)
            {
              
                  t = da / (nx * (va.cx - vs.cx) + ny * (va.cy - vs.cy) +  nz * (va.cz - vs.cz) );
                  dw = vecOut[it];   
                          dw.cx = va.cx + (vs.cx - va.cx) * t;
                          dw.cy = va.cy + (vs.cy - va.cy) * t;
                          dw.cz = va.cz + (vs.cz - va.cz) * t;
                 
                       it += 1; 
                       
                  if (ds < 0)
                  {              
                    vecOut[it].copyVert(va);
                    it += 1;
                  }
            }//endif
            
      }//nexti
      
      if (it < 3) { return -1;}
      
      ret1.a.copyVert(vecOut[0]);
      ret1.b.copyVert(vecOut[1]);
      ret1.c.copyVert(vecOut[2]);
      
      if (it == 3) { return 1; }
      
      ret2.a.copyVert(vecOut[0]);
      ret2.b.copyVert(vecOut[2]);
      ret2.c.copyVert(vecOut[3]);
      
      
        return 2;
    }//cuttriplane

}//xcutter



  internal class xVec
  {
    public var x:Number = 0;
    public var y:Number = 0;
    public var z:Number = 0;
    
    public function xVec(x_:Number = 0, y_:Number = 0, z_:Number = 0):void        {          x = x_;     y = y_;     z = z_;        }
    public function addVec(a:xVec):void        {  x += a.x;  y += a.y;  z += a.z;  }
    public function subVec(a:xVec):void        {   x -= a.x;  y -= a.y;  z -= a.z;  }
    public static function getVecMulNum(a:xVec, b:Number):xVec  { return new xVec(a.x * b, a.y * b, a.z * b); }
    
    public function copyVec(a:xVec):void      {   x = a.x;  y = a.y;  z = a.z;      }
    public function mulNum(b:Number):void       {         x *= b; y *= b; z *= b;      }
        

  }//xvec
  
  
  internal class xQuat
  {
      public var x:Number = 0;
      public var y:Number = 0;
      public var z:Number = 0;
      public var w:Number = 1;

        //multiply by other quaternion
        public function mul(b:xQuat):void
        {
            //temp values
            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 normalise():void
        {
            var mag:Number;
            
            mag = (x * x) + (y * y) + (z * z) + (w * w);
                if (mag == 1.0) return; //already normal
                if (mag == 0) { x = 0;  y = 0;  z = 0;  w = 1; return; }
            mag = 1.0 / Math.sqrt(mag);
            
            x *= mag;   y *= mag;    z *= mag;   w *= mag;
        }//norm

        public function setVecSide(v:xVec):void
        {   v.x = 1.0 - 2.0 * ( y*y + z*z );            v.y = 2.0 * ( x*y + z*w );            v.z = 2.0 * ( x*z - y*w ); }

      public function setVecUp(v:xVec):void
        {   v.x = 2.0 * ( x*y - z*w );          v.y = 1.0 - 2.0 * ( x*x + z*z );          v.z = 2.0 * ( y*z + x*w );       }

      public function setVecFront(v:xVec):void
        {   v.x = 2.0 * ( x*z + y*w );          v.y = 2.0 * ( y*z - x*w );          v.z = 1.0 - 2.0 * ( x*x + y*y );       }

      
  }//xquat



    internal class xFrustum 
    {
        
        public function xFrustum() 
        {
            //setPerspective(90, 465 / 465, 1, 500);
              setPerspective(90, 1, 1, 500);
      
        }//ctor
        
        public var ftl:xVec=new xVec(), ftr:xVec=new xVec(), fbl:xVec=new xVec(), fbr:xVec=new xVec(); //front points
        public var ntl:xVec=new xVec(), ntr:xVec=new xVec(), nbl:xVec=new xVec(), nbr:xVec=new xVec(); //near points

        public var pa:xVec=new xVec(), pb:xVec=new xVec(), pc:xVec=new xVec(), pd:xVec=new xVec(), pe:xVec=new xVec(), pf:xVec=new xVec();
        public var norma:xVec=new xVec(), normb:xVec=new xVec(), normc:xVec=new xVec(), normd:xVec=new xVec(), norme:xVec=new xVec(), normf:xVec=new xVec();

    
        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 var ma:xVec = new xVec(), mb:xVec = new xVec();
        
        public function setPerspective( fovdeg_:Number = 90, aspect_:Number=1.33, nearDist_:Number=1,  farDist_:Number=300):void
        {

            //http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-implementation/
            //tang = (float)tan(ANG2RAD * angle * 0.5) ;    
            
            fov = fovdeg_;
            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 temp_pos:xVec = new xVec();

        
        //sets the frustum points and planes
        //based on a position and orientation
        //todo: make mouse coord calculation seperate(?)
        public function setPoints( pos:xVec, ori:xQuat, umx:Number=0, umy:Number=0):void
        {
            //todo .. replace new xVec with static ones

            var side:xVec, up:xVec, front:xVec;
            side = new xVec();
            up = new xVec();
            front = new xVec();

            ori.setVecFront(front);
            ori.setVecSide(side);
            ori.setVecUp(up);

            var fc:xVec, nc:xVec;
            fc = new xVec();
            nc = new xVec();

            //dividing by two doesnt seem to work out ok
            //not sure why they put that in the lighthouse3d tut

            var nh:Number, nw:Number, fh:Number, fw:Number; 
                nh = nearHeight;// * 0.5f;
                nw = nearWidth; //* 0.5f;

                fh = farHeight; //* 0.5f;
                fw = farWidth; //* 0.5f;

            var farUp:xVec, farSide:xVec;
            var nearUp:xVec, nearSide:xVec;
            farUp = new xVec(); farSide = new xVec();
            nearUp = new xVec(); nearSide = new xVec();

                farUp.copyVec(up); farUp.mulNum(fh);
            //    farUp = up * fh;
                farSide.copyVec(side); farSide.mulNum(fw);
            //    farSide = side * fw;

                nearUp.copyVec(up); nearUp.mulNum(nh);
            //    nearUp = up * nh;
                nearSide.copyVec(side); nearSide.mulNum(nw);
            //    nearSide = side * nw;

            fc.copyVec(front); fc.mulNum(farDist); fc.addVec(pos); 
            //fc = pos + front * farDist;
            
            ftl.copyVec(fc); ftl.addVec(farUp); ftl.subVec(farSide);
            //    ftl = fc + farUp - farSide;
            ftr.copyVec(fc); ftr.addVec(farUp); ftr.addVec(farSide);
            //    ftr = fc + farUp + farSide;
            fbl.copyVec(fc); fbl.subVec(farUp); fbl.subVec(farSide);
            //    fbl = fc - farUp - farSide;
            fbr.copyVec(fc); fbr.subVec(farUp); fbr.addVec(farSide);
            //    fbr = fc - farUp + farSide;

            nc.copyVec(front); nc.mulNum(nearDist); nc.addVec(pos); 
            //nc = pos + front * nearDist;

            ntl.copyVec(nc); ntl.addVec(nearUp); ntl.subVec(nearSide);
            //    ntl = nc + nearUp - nearSide;
            ntr.copyVec(nc); ntr.addVec(nearUp); ntr.addVec(nearSide);
            //    ntr = nc + nearUp + nearSide;
            nbl.copyVec(nc); nbl.subVec(nearUp); nbl.subVec(nearSide);
            //    nbl = nc - nearUp - nearSide;
            nbr.copyVec(nc); nbr.subVec(nearUp); nbr.addVec(nearSide);
            //    nbr = nc - nearUp + nearSide;

                
            ma.copyVec(fc); ma.addVec( xVec.getVecMulNum(farUp, umy) ); ma.addVec( xVec.getVecMulNum(farSide, umx) );
            //sa = fc + (farUp * umy) + (farSide * umx);


            mb.copyVec(nc); mb.addVec( xVec.getVecMulNum(nearUp, umy) ); mb.addVec( xVec.getVecMulNum(nearSide, umx) );
            //sb = nc + (nearUp * umy) + (nearSide * umx)
            
            
            setNormals();
        }//setpoints
        
        //todo: i guess it would be enough to do in 2D (?)
        
        public function isSphereInside2(px:Number, py:Number, pz:Number, r:Number):Boolean
        {
         
        
            var dist:Number;
            var rad:Number;
            
            rad = -r;

            dist = (px-pa.x) * norma.x + (py-pa.y)*norma.y + (pz-pa.z)*norma.z;
            if (dist < rad) return false;
        
            dist = (px-pb.x) * normb.x + (py-pb.y)*normb.y + (pz-pb.z)*normb.z;
            if (dist < rad) return false;
    
            dist = (px-pc.x) * normc.x + (py-pc.y)*normc.y + (pz-pc.z)*normc.z;
            if (dist < rad) return false;

            dist = (px-pd.x) * normd.x + (py-pd.y)*normd.y + (pz-pd.z)*normd.z;
            if (dist < rad) return false;

            dist = (px-pe.x) * norme.x + (py-pe.y)*norme.y + (pz-pe.z)*norme.z;
            if (dist < rad) return false;

            dist = (px-pf.x) * normf.x + (py-pf.y)*normf.y + (pz-pf.z)*normf.z;
            if (dist < rad) return false;
    
            return true; 
            
        }//issphereinside
        
        
        public function isSphereInside(p:xVec, rad:Number):Boolean
        {
            var dist:Number;
            rad = -rad;

            dist = (p.x-pa.x) * norma.x + (p.y-pa.y)*norma.y + (p.z-pa.z)*norma.z;
            if (dist < rad) return false;
        
            dist = (p.x-pb.x) * normb.x + (p.y-pb.y)*normb.y + (p.z-pb.z)*normb.z;
            if (dist < rad) return false;
    
            dist = (p.x-pc.x) * normc.x + (p.y-pc.y)*normc.y + (p.z-pc.z)*normc.z;
            if (dist < rad) return false;

            dist = (p.x-pd.x) * normd.x + (p.y-pd.y)*normd.y + (p.z-pd.z)*normd.z;
            if (dist < rad) return false;

            dist = (p.x-pe.x) * norme.x + (p.y-pe.y)*norme.y + (p.z-pe.z)*norme.z;
            if (dist < rad) return false;

            dist = (p.x-pf.x) * normf.x + (p.y-pf.y)*normf.y + (p.z-pf.z)*normf.z;
            if (dist < rad) return false;
    
            return true; 
        }//issphere_inside


        public function isPointInside(p:xVec):Boolean
        {

            //todo -- opt
            //dist variable is not really needed here
            //so can jut put the calculations in the if
            var dist:Number;
            
        
            // check distance to planes
            // distance = (object position - cam position) dot (plane normal)

            //check point distance to near and far planes first
            //if its behind any of them we know its outside the frustum

                dist = (p.x-pa.x) * norma.x + (p.y-pa.y)*norma.y + (p.z-pa.z)*norma.z;
                if (dist < 0) return false;
            
                dist = (p.x-pb.x) * normb.x + (p.y-pb.y)*normb.y + (p.z-pb.z)*normb.z;
                if (dist < 0) return false;
        
                dist = (p.x-pc.x) * normc.x + (p.y-pc.y)*normc.y + (p.z-pc.z)*normc.z;
                if (dist < 0) return false;

                dist = (p.x-pd.x) * normd.x + (p.y-pd.y)*normd.y + (p.z-pd.z)*normd.z;
                if (dist < 0) return false;

                dist = (p.x-pe.x) * norme.x + (p.y-pe.y)*norme.y + (p.z-pe.z)*norme.z;
                if (dist < 0) return false;

                dist = (p.x-pf.x) * normf.x + (p.y-pf.y)*normf.y + (p.z-pf.z)*normf.z;
                if (dist < 0) return false;
        
            return true;
        }//ispinside

        
        public function calcNorm(norm:xVec, c:xVec, d:xVec, e:xVec, f:xVec):void
        {        
            var ax:Number, ay:Number, az:Number;
            var bx:Number, by:Number, bz:Number;
            var cx:Number, cy:Number, cz:Number;
            var dist:Number;
            
            ax = c.x - d.x;
            ay = c.y - d.y;
            az = c.z - d.z;
            
            bx = e.x - f.x;
            by = e.y - f.y;
            bz = e.z - f.z;
            
            cx = (ay * bz) - (az * by);
            cy = (az * bx) - (ax * bz);
                cz = (ax * by) - (ay * bx);
                
            dist = Math.sqrt( (cx * cx) + (cy * cy) + (cz * cz) );
            if (dist == 0) { norm.x = 0; norm.y = 0; norm.z = 0; }
            else
            {
                norm.x = cx / dist;
                norm.y = cy / dist;
                norm.z = cz / dist;
            }//endif
            
        }//calcplane
        
        
        public function setNormals():void
            {
                //near
                pa.x = (ntr.x + nbl.x) * 0.5;
                pa.y = (ntr.y + nbl.y) * 0.5;
                pa.z = (ntr.z + nbl.z) * 0.5;
                calcNorm(norma, ntr, nbr, nbl, ntr);
                
            
                //far
                pb.x = (ftr.x + fbl.x) * 0.5;
                pb.y = (ftr.y + fbl.y) * 0.5;
                pb.z = (ftr.z + fbl.z) * 0.5;
                calcNorm(normb, ftr, fbr, ftr, fbl);

                //left
                pc.x = (ftl.x + fbl.x + ntl.x + nbl.x) / 4;
                pc.y = (ftl.y + fbl.y + ntl.y + nbl.y) / 4;
                pc.z = (ftl.z + fbl.z + ntl.z + nbl.z) / 4;
                calcNorm(normc, ftl, fbl, ftl, ntl);

                //right
                pd.x = (ftr.x + fbr.x + ntr.x + nbr.x) / 4;
                pd.y = (ftr.y + fbr.y + ntr.y + nbr.y) / 4;
                pd.z = (ftr.z + fbr.z + ntr.z + nbr.z) / 4;
                calcNorm(normd, ftr, ntr, ftr, fbr);
                
                //top
                pe.x = (ftr.x + ftl.x + ntr.x + ntl.x) / 4;
                pe.y = (ftr.y + ftl.y + ntr.y + ntl.y) / 4;
                pe.z = (ftr.z + ftl.z + ntr.z + ntl.z) / 4;
                calcNorm(norme, ftr, ftl, ftr, ntr);

                //bottom
                pf.x = (fbr.x + fbl.x + nbr.x + nbl.x) / 4;
                pf.y = (fbr.y + fbl.y + nbr.y + nbl.y) / 4;
                pf.z = (fbr.z + fbl.z + nbr.z + nbl.z) / 4;
                calcNorm(normf, fbl, nbl, fbr, fbl);
                
            }//setnormals

        
        
        
        
    }//classend