//Повороты вокруг трех осей OX,OY,OZ, масштабирование и параллельный перенос

//Параметры вызова процедуры
//mdlnum    - номер объекта
//alpha     - угол поворото вокруг оси OX
//MatrixMul - при первом повороте должно быть FALSE
void RotateObjectOX(dword mdlnum, float alpha)
{
  //[x'] [1      0          0       0]   [x]
  //[y']=[0  cos(alpha) -sin(alpha) 0] * [y]
  //[z'] [0  sin(alpha)  cos(alpha) 0]   [z]
  //[1 ] [0      0          0       1]   [1]

  //Очищаем матрицу от хлама
  ClearTempMatrix();

  //Заполняем матрицу значениями
  $fld alpha
  $fsincos
  $fst Matrix[5*4]
  $fstp Matrix[10*4]
  $fst Matrix[9*4]
  $fchs
  $fstp Matrix[6*4]

  EDI=Object[mdlnum].OffsStatusMatrix;
  ESI=#Matrix;
  EDX=EDI;
  __MulMatrixAMatrixB_4x4();
}


//Параметры вызова процедуры
//mdlnum    - номер объекта
//alpha     - угол поворото вокруг оси OY
//MatrixMul - при первом повороте должно быть FALSE
void RotateObjectOY(dword mdlnum, float alpha)
{
  //y'=y
  //x'=x*cos(alpha)-z*sin(alpha)
  //z'=x*sin(alpha)+z*cos(alpha)
  //[x'] [cos(alpha)      0  sin(alpha)    0]   [x]
  //[y']=[    0           1       0        0] * [y]
  //[z'] [-sin(alpha)     0  cos(alpha)    0]   [z]
  //[1 ] [    0           0       0        1]   [1]

  //Очищаем матрицу от хлама
  ClearTempMatrix();

  //Заполняем матрицу значениями
  $fld alpha
  $fsincos
  $fst Matrix[0]
  $fstp Matrix[10*4]
  $fst Matrix[2*4]
  $fchs
  $fstp Matrix[8*4]

//  ESI=Object[mdlnum].OffsStatusMatrix;
//  EDI=#Matrix;
//  EDX=ESI;
//  MulMatrixAMatrixB_4x4();
  EDI=Object[mdlnum].OffsStatusMatrix;
  ESI=#Matrix;
  EDX=EDI;
  __MulMatrixAMatrixB_4x4();
}


//Параметры вызова процедуры
//mdlnum    - номер объекта
//alpha     - угол поворото вокруг оси OZ
//MatrixMul - при первом повороте должно быть FALSE
void RotateObjectOZ(dword mdlnum, float alpha)
{
  //z'=z
  //x'=x*cos(alpha)-y*sin(alpha)
  //y'=x*sin(alpha)+y*cos(alpha)
  //[x'] [cos(alpha)  -sin(alpha)   0   0]   [x]
  //[y']=[sin(alpha)   cos(alpha)   0   0] * [y]
  //[z'] [    0            0        1   0]   [z]
  //[1 ] [    0            0        0   1]   [1]

  //Очищаем матрицу от хлама
  ClearTempMatrix();

  //Заполняем матрицу значениями
  $fld alpha
  $fsincos
  $fst Matrix[0]
  $fstp Matrix[5*4]
  $fst Matrix[4*4]
  $fchs
  $fstp Matrix[1*4]

//  ESI=Object[mdlnum].OffsStatusMatrix;
//  EDI=#Matrix;
//  EDX=ESI;
//  MulMatrixAMatrixB_4x4();
  EDI=Object[mdlnum].OffsStatusMatrix;
  ESI=#Matrix;
  EDX=EDI;
  __MulMatrixAMatrixB_4x4();
}

void ScaleObject(dword mdlnum, float scalex,scaley,scalez)
{
  ClearTempMatrix();

  Matrix[0]=scalex;
  Matrix[5*4]=scaley;
  Matrix[10*4]=scalez;

/*  ESI=Object[mdlnum].OffsStatusMatrix;
  EDI=#Matrix;
  EDX=ESI;
  MulMatrixAMatrixB_4x4();*/
  EDI=Object[mdlnum].OffsStatusMatrix;
  ESI=#Matrix;
  EDX=EDI;
  __MulMatrixAMatrixB_4x4();
}


void MoveObject(dword mdlnum, float sx,sy,sz)
{
  //Очищаем матрицу от хлама
  ClearTempMatrix();

  //Заполнение временной матрицы
  Matrix[3*4]=sx;
  Matrix[7*4]=sy;
  Matrix[11*4]=sz;

/*  ESI=Object[mdlnum].OffsStatusMatrix;
  EDI=#Matrix;
  EDX=ESI;
  MulMatrixAMatrixB_4x4();*/
  EDI=Object[mdlnum].OffsStatusMatrix;
  ESI=#Matrix;
  EDX=EDI;
  __MulMatrixAMatrixB_4x4();
}

CameraView()
 float lp,lq,lr;
 dword i;
{
//    [ qx*2/xSize  rx*2/ySize  px/dist ]   [ qx1 rx1 px1 ]
//T = [ qy*2/xSize  ry*2/ySize  py/dist ] = [ qy1 ry1 py1 ]
//    [ qz*2/xSize  rz*2/ySize  pz/dist ]   [ qz1 rz1 pz1 ]
//
//     [ qx1/lq  qy1/lq  qz1/lq ]
//T1 = [ rx1/lr  ry1/lr  rz1/lr ]
//     [ px1/lp  py1/lp  pz1/lp ]
//где
//
//lp = px1*px1 + py1*py1 + pz1*pz1
//lq = qx1*qx1 + qy1*qy1 + qz1*qz1
//lr = rx1*rx1 + ry1*ry1 + rz1*rz1
 //Делае поворот базиса по OX и OY
 ClearMatrix(dword #Matrix);
 $fld Camera.RotateOX
 $fsincos
 $fst Matrix[5*4]
 $fstp Matrix[10*4]
 $fst Matrix[9*4]
 $fchs
 $fstp Matrix[6*4]
 _MulMatrixAVectorA_4x4(dword #Matrix, dword #Camera.rx, dword #Camera.rx1);
 _MulMatrixAVectorA_4x4(dword #Matrix, dword #Camera.px, dword #Camera.px1);
 _MulMatrixAVectorA_4x4(dword #Matrix, dword #Camera.qx, dword #Camera.qx1);
 ClearMatrix(dword #Matrix);
 $fld Camera.RotateOY
 $fsincos
 $fst Matrix[0]
 $fstp Matrix[10*4]
 $fst Matrix[2*4]
 $fchs
 $fstp Matrix[8*4]
 _MulMatrixAVectorA_4x4(dword #Matrix, dword #Camera.rx1, dword #Camera.rx1);
 _MulMatrixAVectorA_4x4(dword #Matrix, dword #Camera.px1, dword #Camera.px1);
 _MulMatrixAVectorA_4x4(dword #Matrix, dword #Camera.qx1, dword #Camera.qx1);

 //Вычисляем qx1,qy1,qz1,lq
 $fld Camera.qx1
 $fdiv HalfSizeX
 $fst Camera.qx1
 $fmul ST,ST(0)
 $fld Camera.qy1
 $fdiv HalfSizeX
 $fst Camera.qy1
 $fmul ST,ST(0)
 $fld Camera.qz1
 $fdiv HalfSizeX
 $fst Camera.qz1
 $fmul ST,ST(0)
 $faddp ST(1)
 $faddp ST(1)
 $fstp lq

 //Вычисляем rx1,ry1,rz1,lr
 $fld Camera.rx1
 $fdiv HalfSizeY
 $fst Camera.rx1
 $fmul ST,ST(0)
 $fld Camera.ry1
 $fdiv HalfSizeY
 $fst Camera.ry1
 $fmul ST,ST(0)
 $fld Camera.rz1
 $fdiv HalfSizeY
 $fst Camera.rz1
 $fmul ST,ST(0)
 $faddp ST(1)
 $faddp ST(1)
 $fstp lr

 //Вычисляем px1,py1,pz1,lp
 $fld Camera.px1
 $fdiv dist
 $fst Camera.px1
 $fmul ST,ST(0)
 $fld Camera.py1
 $fdiv dist
 $fst Camera.py1
 $fmul ST,ST(0)
 $fld Camera.pz1
 $fdiv dist
 $fst Camera.pz1
 $fmul ST,ST(0)
 $faddp ST(1)
 $faddp ST(1)
 $fstp lp

//     [ qx1/lq  qy1/lq  qz1/lq  0 ]
//T1 = [ rx1/lr  ry1/lr  rz1/lr  0 ]
//     [ px1/lp  py1/lp  pz1/lp  0 ]
//     [   0       0       0     1 ]
 //Очищение временной матрицы
 ClearMatrix(dword #CameraMatrix);
 //Заполняем матрицу камеры нужными значениями
 $fld Camera.qx1
 $fdiv lq
 $fstp CameraMatrix[0]
 $fld Camera.qy1
 $fdiv lq
 $fstp CameraMatrix[1*4]
 $fld Camera.qz1
 $fdiv lq
 $fstp CameraMatrix[2*4]

 $fld Camera.rx1
 $fdiv lr
 $fstp CameraMatrix[4*4]
 $fld Camera.ry1
 $fdiv lr
 $fstp CameraMatrix[5*4]
 $fld Camera.rz1
 $fdiv lr
 $fstp CameraMatrix[6*4]

 $fld Camera.px1
 $fdiv lp
 $fstp CameraMatrix[8*4]
 $fld Camera.py1
 $fdiv lp
 $fstp CameraMatrix[9*4]
 $fld Camera.pz1
 $fdiv lp
 $fstp CameraMatrix[10*4]

 //Поворачаваем камеру вокруг OZ
 ClearMatrix(dword #CameraRotateMatrix);
 $fld Camera.RotateOZ
 $fsincos
 $fst CameraRotateMatrix[0]
 $fstp CameraRotateMatrix[5*4]
 $fst CameraRotateMatrix[4*4]
 $fchs
 $fstp CameraRotateMatrix[1*4]

 //Заполнение временной матрицы матрицей параллельного переноса
 ClearMatrix(dword #Matrix);
 Matrix[3*4]=-Camera.sx;
 Matrix[7*4]=-Camera.sy;
 Matrix[11*4]=-Camera.sz;
 _MulMatrixAMatrixB_4x4(dword #Matrix, dword #CameraRotateMatrix, dword #CameraRotateMatrix);

 _MulMatrixAMatrixB_4x4(dword #CameraMatrix, dword #CameraRotateMatrix, dword #CameraMatrix);

 //Заполнение временной матрицы матрицей параллельного переноса
 ClearMatrix(dword #Matrix);
 Matrix[3*4]=0;
 Matrix[7*4]=0;
 Matrix[11*4]=-dist;
 _MulMatrixAMatrixB_4x4(dword #Matrix, dword #CameraMatrix, dword #CameraMatrix);

 FOR (i=0; i<NumObjects; i++){
     EDI=Object[i].OffsStatusMatrix;
     ESI=#CameraMatrix;
     EDX=EDI;
     __MulMatrixAMatrixB_4x4();
 }
}


CreateObjectsStatusMatrix()
 dword i;
{
 for (i=0; i<NumObjects; i++){
     ClearModelStatusMatrix(dword i);
     ScaleObject(dword i, float 1,float 1,float 1);
     RotateObjectOX(dword i, float Object[i].rx);
     RotateObjectOY(dword i, float Object[i].ry);
     RotateObjectOZ(dword i, float Object[i].rz);
     MoveObject(dword i,float Object[i].x,float Object[i].y,float Object[i].z);
 }
 //Учитываем положение камеры
 CameraView();
}



