var n = (document.layers) ? 1:0;

var xCoefficient       // used in viewport transformations
var yCoefficient       // used in viewport transformations

var mModelView  = new Array (new Array (1000, 0, 0, 0), new Array (0, 1000, 0, 0), new Array (0, 0, 1000, 0), new Array (0, 0, 0, 1000))
var mProjection = new Array (new Array (1000, 0, 0, 0), new Array (0, 1000, 0, 0), new Array (0, 0, 1000, 0), new Array (0, 0, 0, 1000))
var mModelViewStack = new Array ()
var mProjectionStack = new Array ()
var mv = 1
var point =  new Array (0, 0, 0, 1.0)
var sortSprites = 1
var halffov = 1

var m = new Array ()
var myVPos = new Array ()
var pos2d = new Array ()
var pos3d = new Array ()
var SpritePosList3d = new Array ()
var ebeneOnOff = new Array ()
var punktOnOff = new Array ()
var normalenVektor = new Array ()
var ebenenVektor2 = new Array ()
//var normalenVektor = new Array ()
var skalarProdukt = new Array ()

var s,  rotation, lastfrustum, zList, vPList
var zSlider, ySlider, xSlider, xScale, yScale, zScale, Frustum, roton, rox, roy, roz


function xFormPoint(p){

  m = Matrix1x4Mult(p, mModelView)                    
  
  if (m != 0){ m = Matrix1x4Mult(m, mProjection);}  
  else 
        {
    alert( "ERROR!:  Point couldn't be converted: " + p)
    return 0
        }
  
  pos3d = m

  m = PerspectiveDivide(m)                            

  if (m != 0){m = ViewPortXForm(m);}                  
  
  
  pos2d = m

  return m
}

function pFrustum(left, right, bottom, top, near, far){
  nn = 2.0*near
  rl = right - left
  tb = top - bottom
  fn = far - near

  mProjection[0][0] = Math.round(1000*nn/rl)
  mProjection[0][1] = 0
  mProjection[0][2] = Math.round(1000*(right+left)/rl)
  mProjection[0][3] = 0
  
  mProjection[1][0] = 0
  mProjection[1][1] = (1000*nn/tb)
  mProjection[1][2] = Math.round(1000*(top+bottom)/tb)
  mProjection[1][3] = 0
  
  mProjection[2][0] = 0
  mProjection[2][1] = 0
  mProjection[2][2] = Math.round(1000*-(far+near)/fn)
  mProjection[2][3] = Math.round(1000*-(far*nn)/fn)
  
  mProjection[3][0] = 0
  mProjection[3][1] = 0
  mProjection[3][2] = -1000
  mProjection[3][3] = 0
  
  halffov = (1.5708 / Math.abs(Math.atan(top / near)))
  return 1  
}


function pOrtho (left, right, bottom, top, near, far){
  rl = right - left
  tb = top - bottom
  fn = far - near
  
  mProjection[0][0] = Math.round(2000/rl)
  mProjection[0][1] = 0
  mProjection[0][2] = 0
  mProjection[0][3] = Math.round(1000*(right+left)/rl)
  
  mProjection[1][0] = 0
  mProjection[1][1] = Math.round(2000/tb)
  mProjection[1][2] = 0
  mProjection[1][3] = Math.round(1000*(top+bottom)/tb)
  
  mProjection[2][0] = 0
  mProjection[2][1] = 0
  mProjection[2][2] = Math.round(-200/fn)
  mProjection[2][3] = Math.round(1000*(far+near)/fn)
  
  mProjection[3][0] = 0
  mProjection[3][1] = 0
  mProjection[3][2] = 0
  mProjection[3][3] = 1000
  
  halffov = -1
  return 1
}


function pViewPort (x, y, width, height){
  xCoefficient = (width/2)  + x
  yCoefficient = (height/2) + y
  return 1
}

function mSelectMatrix (arg){
  if ((arg) == "Projection"){mv = 0;}else{mv = 1}
  return 1
} 

// Push current matrix onto stack, current matrix is a copy of what is on top of the stack until you change it.
function mPush(){
  if (mv)
        {
    mModelViewStack[0] = mModelView
    }
  else
        {
    mProjectionStack[0] = mProjection
    }
  return 1
}


// Load the identity matrix into the current matrix

function mLoadIdentity(){
  if (mv)
        {
        mModelView  = new Array (new Array (1000, 0, 0, 0), new Array (0, 1000, 0, 0), new Array (0, 0, 1000, 0), new Array (0, 0, 0, 1000))
    }
  else
        {
        mProjection = new Array (new Array (1000, 0, 0, 0), new Array (0, 1000, 0, 0), new Array (0, 0, 1000, 0), new Array (0, 0, 0, 1000))
    }
  return 1
}

function xTranslate(x, y, z){
  m1Sub1 = new Array (1000, 0, 0, Math.round(1000*x))
  m1Sub2 = new Array (0, 1000, 0, Math.round(1000*y))
  m1Sub3 = new Array (0, 0, 1000, Math.round(1000*z))
  m1Sub4 = new Array (0, 0, 0, 1000)
  m1 = new Array (m1Sub1,m1Sub2,m1Sub3,m1Sub4)
  mModelView = Matrix4x4Mult(m1, mModelView)
  if (mModelView != 0){return 1;} else {return 0;}
}

function xRotateX(a){
  m3Sub1 = new Array (1000, 0, 0, 0)
  m3Sub2 = new Array (0, Math.round(1000*Math.cos(a)), Math.round(1000*-Math.sin(a)), 0)
  m3Sub3 = new Array (0, Math.round(1000*Math.sin(a)), Math.round(1000*Math.cos(a)), 0)
  m3Sub4 = new Array (0, 0, 0, 1000)
  m3 = new Array (m3Sub1,m3Sub2,m3Sub3,m3Sub4)

  mModelView = Matrix4x4Mult(m3, mModelView)
  if (mModelView != 0){return 1;} else {return 0;}
}

function xRotateY(a){
  m4 = new Array (new Array (Math.round(1000*Math.cos(a)), 0, Math.round(1000*Math.sin(a)), 0), new Array (0, 1000, 0, 0), new Array (Math.round(1000*-Math.sin(a)), 0, Math.round(1000*Math.cos(a)), 0), new Array (0, 0, 0, 1000))
  mModelView = Matrix4x4Mult(m4, mModelView)
  if (mModelView != 0){return 1;} else {return 0;}
}

function xRotateZ(a){
  m5 = new Array (new Array (Math.round(1000*Math.cos(a)), Math.round(1000*-Math.sin(a)), 0, 0), new Array (Math.round(1000*Math.sin(a)), Math.round(1000*Math.cos(a)), 0, 0), new Array (0, 0, 1000, 0),  new Array (0, 0, 0, 1000))
  mModelView = Matrix4x4Mult(m5, mModelView)
  if (mModelView != 0){return 1;} else {return 0;}
}

function DoxScale(x, y, z){
  m2 = new Array (new Array (Math.round(1000*x), 0, 0, 0), new Array (0, Math.round(1000*y), 0, 0), new Array (0, 0, Math.round(1000*z), 0), new Array (0, 0, 0, 1000))
  mModelView = Matrix4x4Mult(m2, mModelView)
  if (mModelView != 0){return 1;} else {return 0;}
}


function pilotView(plane_x, plane_y, plane_z, roll, pitch, heading){
  roll = (roll/360.0) * (2.0*Math.PI)
  pitch = (pitch/360.0) * (2.0*Math.PI)
  heading = (heading/360.0) * (2.0*Math.PI)
  if (xRotateZ(roll) && xRotateY(pitch) && xRotateX(heading) && xTranslate(-plane_x, -plane_y, -plane_z)){return 1;} else {return 0;}
}


function polarView(distance, twist, elevation, azimuth){
  if (xTranslate(0, 0, -distance) && xRotateZ(-twist) && xRotateX(-elevation) && xRotateZ(azimuth)){return 1;} else {return 0;}
}


function PerspectiveDivide(thePoint){
  if (thePoint.length == 4){
    w = thePoint[3]
    if (w != 0){
      x = thePoint[0]
      y = thePoint[1]
      z = thePoint[2]

      
      return new Array (x/w, y/w, Math.abs(z/w))
      }
    else
      {
      return 0
      }
    }
  else
    {
    return 0
    } 
}


function ViewPortXForm(thePoint){
  if (thePoint.length == 3){
    return new Array ((thePoint[0] + 1.0) * xCoefficient, (thePoint[1] + 1.0) * yCoefficient, thePoint[2]);}
  else{
    return 0;}
}


function Matrix4x4Mult(a,b){
  if (a[0].length == b.length){
    a11 = e(a,1,1) 
    a21 = e(a,2,1) 
    a31 = e(a,3,1) 
    a41 = e(a,4,1) 
    a12 = e(a,1,2) 
    a22 = e(a,2,2) 
    a32 = e(a,3,2) 
    a42 = e(a,4,2) 
    a13 = e(a,1,3) 
    a23 = e(a,2,3) 
    a33 = e(a,3,3) 
    a43 = e(a,4,3) 
    a14 = e(a,1,4) 
    a24 = e(a,2,4) 
    a34 = e(a,3,4) 
    a44 = e(a,4,4) 
    b11 = e(b,1,1) 
    b21 = e(b,2,1) 
    b31 = e(b,3,1) 
    b41 = e(b,4,1) 
    b12 = e(b,1,2) 
    b22 = e(b,2,2) 
    b32 = e(b,3,2) 
    b42 = e(b,4,2)  
    b13 = e(b,1,3) 
    b23 = e(b,2,3) 
    b33 = e(b,3,3) 
    b43 = e(b,4,3) 
    b14 = e(b,1,4) 
    b24 = e(b,2,4) 
    b34 = e(b,3,4) 
    b44 = e(b,4,4) 
    return new Array(new Array(((a11*b11)+(a12*b21)+(a13*b31)+(a14*b41))/1000,((a11*b12)+(a12*b22)+(a13*b32)+(a14*b42))/1000,((a11*b13)+(a12*b23)+(a13*b33)+(a14*b43))/1000,((a11*b14)+(a12*b24)+(a13*b34)+(a14*b44))/1000),new Array(((a21*b11)+(a22*b21)+(a23*b31)+(a24*b41))/1000,((a21*b12)+(a22*b22)+(a23*b32)+(a24*b42))/1000,((a21*b13)+(a22*b23)+(a23*b33)+(a24*b43))/1000,((a21*b14)+(a22*b24)+(a23*b34)+(a24*b44))/1000),new Array(((a31*b11)+(a32*b21)+(a33*b31)+(a34*b41))/1000,((a31*b12)+(a32*b22)+(a33*b32)+(a34*b42))/1000,((a31*b13)+(a32*b23)+(a33*b33)+(a34*b43))/1000,((a31*b14)+(a32*b24)+(a33*b34)+(a34*b44))/1000),new Array(((a41*b11)+(a42*b21)+(a43*b31)+(a44*b41))/1000,((a41*b12)+(a42*b22)+(a43*b32)+(a44*b42))/1000,((a41*b13)+(a42*b23)+(a43*b33)+(a44*b43))/1000,((a41*b14)+(a42*b24)+(a43*b34)+(a44*b44))/1000))
  }
  else
  {
    alert("Error: Could not multiply matrices, a.cols != b.rows != 4.")
    return 0
  }
}

function Matrix1x4Mult(c, b){
  if (b[0].length == c.length){
    a = new Array((c[0]*1000), (c[1]*1000), (c[2]*1000), (c[3]*1000))
    
    a1 = a[0]
    a2 = a[1]
    a3 = a[2]
    a4 = a[3]

    return new Array(((e(b,1,1)*a1)+(e(b,1,2)*a2)+(e(b,1,3)*a3)+(e(b,1,4)*a4))/100000.0,((e(b,2,1)*a1)+(e(b,2,2)*a2)+(e(b,2,3)*a3)+(e(b,2,4)*a4))/100000.0,((e(b,3,1)*a1)+(e(b,3,2)*a2)+(e(b,3,3)*a3)+(e(b,3,4)*a4))/100000.0,((e(b,4,1)*a1)+(e(b,4,2)*a2)+(e(b,4,3)*a3)+(e(b,4,4)*a4))/100000.0)
  }
else
  {
    alert("Error: Could not multiple matrices, a.cols != b.rows.")
    return 0
  }
}


function e(m, a, b){
  return m[a-1][b-1]
}

function s(m, a, b, c){
  m[a-1][b-1] = c
}
