#include <stdio.h>
#include <dos.h>
#include <math.h>
#include <string.h>
#include <malloc.h>
#include "3dproj.h"
#include "3ddefs.h"
#include "3dprep.h"
#include "3dvarse.h"

float  angle ( float ang1, float ang2 )
{
  if ( (ang2>-0.01)&&(ang2<0.01)) ang2=0.01;
  return ( atan ( ang1 / ang2 ) );
}

float  pythag3d(float a,float b,float c)
{
  return(sqrt(CHK(a*a)+CHK(b*b)+CHK(c*c)));
}

float  pythag2d(float a,float b)
{
  return(sqrt(CHK(a*a)+CHK(b*b)));
}
void  calculate_ship_angles(float x1, float y1, float z1, float x2, float y2, float z2, float *fx, float *fy)
{
  float ax1,ax2,ay1,ay2;
  ay1=angle(x1,z1);
  ax1=angle(y1,z1);
  ay2=angle(x2,z2);  // The angle of the ship
  ax2=angle(y2,z2);
  if(z2<=0 && x2>0) ay2+=PI;
  if(z2<=0 && x2<0) ay2-=PI;
  if(z2<=0 && y2>0) ax2+=PI;
  if(z2<=0 && y2<0) ax2-=PI;
  if(z1<=0 && x1>0) ay1+=PI;
  if(z1<=0 && x1<0) ay1-=PI;
  if(z1<=0 && y1>0) ax1+=PI;
  if(z1<=0 && y1<0) ax1-=PI;
  *fx=ax1-ax2;
  *fy=ay1-ay2;
  if (*fx>PI)  *fx=*fx-PI*2;
  if (*fx<-PI) *fx=*fx+PI*2;
  if (*fy>PI)  *fy=*fy-PI*2;
  if (*fy<-PI) *fy=*fy+PI*2;
}

void  calculate_cos_sin(float *x, float *y, float precos, float presin)
{
  float xold,yold;
  xold=*x;
  yold=*y;
  *x=xold*precos-yold*presin;
  *y=xold*presin+yold*precos;
}

void  rotatesummat(float *x,float *y,float *z,float ax,float ay,float az)
{
  float cax,sax,cay,say,caz,saz;
  cax=cos(a*ax); cay=cos(a*ay); caz=cos(a*az);
  sax=sin(a*ax); say=sin(a*ay); saz=sin(a*az);
  if (ay!=0) calculate_cos_sin(x, z, cay, say);
  if (ax!=0) calculate_cos_sin(z, y, cax, sax);
  if (az!=0) calculate_cos_sin(y, x, caz, saz);
}

void  rotatesummatelse(float *x,float *y,float *z,float cax,float sax,float cay,float say,float caz,float saz)
{
  calculate_cos_sin(x, z, cay, say);
  calculate_cos_sin(z, y, cax, sax);
  calculate_cos_sin(x, y, caz, saz);
}

void  rotatenormals(float x[3],float y[3],float z[3],float cax,float sax,float cay,float say,float caz,float saz)
{
  rotatesummatelse(&x[0],&y[0],&z[0],cax,sax,cay,say,caz,saz);
  rotatesummatelse(&x[1],&y[1],&z[1],cax,sax,cay,say,caz,saz);
  x[2]=0.01*(z[0]*y[1]-y[0]*z[1]);
  y[2]=0.01*(x[0]*z[1]-z[0]*x[1]);
  z[2]=0.01*(y[0]*x[1]-x[0]*y[1]);
}

void  rotatedddwarestyle(int *x,int *y,int *z,float dx0,float dy0,float dz0,float dx2,float dy2,float dz2)
{
  float cosy,cosx,siny,sinx;
  float tempx,tempy,tempz,xold,yold,zold,xdir,ydir,zdir;
  ydir=angle(dx0,dz0);
  if (dz0<=0 && dx0>0) ydir+=PI;
  if (dz0<=0 && dx0<0) ydir-=PI;
  xdir=angle(dy0,pythag2d(dx0,dz0));
  cosx=cos(xdir);
  cosy=cos(ydir);
  sinx=sin(xdir);
  siny=sin(ydir);
  tempx=dx2;
  tempy=dy2;
  tempz=dz2;
  xold=tempx; //Rotate around y
  zold=tempz;
  tempx=(xold*cosy)-(zold*siny);
  tempz=(xold*siny)+(zold*cosy);
  yold=tempy; // rotate around x
  zold=tempz;
  tempy=(yold*cosx)-(zold*sinx);
  tempz=(yold*sinx)+(zold*cosx);
  if (tempx>0) zdir=angle(-tempy ,pythag2d(tempx,tempz));
  else zdir=PI+angle(tempy ,pythag2d(tempx,tempz));
  *y=ydir*10430.37835; // Translate the radians into the dddware 'degrees' (0-65536=0-2pi)
  *x=xdir*10430.37835;
  *z=zdir*10430.37835;
  if (*x>-1 && *x<1) *x=1;
  if (*y>-1 && *y<1) *y=1;
  if (*z>-1 && *z<1) *z=1;
}

int  saferandom(int range)
{
  int temp;
  temp=1+apirandom(range)-(int)(range/2+0.5);
  if (temp==0) temp=1;
  return(temp);
}
void  spinturret(int obj,int g,float aroundx,float aroundy,float aroundz)
{
  float cax,sax,cay,say,caz,saz;
  cax=cos(aroundx*a); cay=cos(aroundy*a); caz=cos(aroundz*a);
  sax=sin(aroundx*a); say=sin(aroundy*a); saz=sin(aroundz*a);
  rotatesummatelse(&o[obj].t[g].sx,&o[obj].t[g].sy,&o[obj].t[g].sz,cax,sax,cay,say,caz,saz);
  rotatesummatelse(&o[obj].t[g].sx2,&o[obj].t[g].sy2,&o[obj].t[g].sz2,cax,sax,cay,say,caz,saz);
  rotatenormals(o[obj].t[g].dx,o[obj].t[g].dy,o[obj].t[g].dz,cax,sax,cay,say,caz,saz);
  rotatedddwarestyle(&o[obj].t[g].rx,&o[obj].t[g].ry,&o[obj].t[g].rz,o[obj].t[g].dx[0],o[obj].t[g].dy[0],o[obj].t[g].dz[0],o[obj].t[g].dx[2],o[obj].t[g].dy[2],o[obj].t[g].dz[2]);
}
void  spinhangerzone(int obj,int g,float aroundx,float aroundy,float aroundz)
{
  float cax,sax,cay,say,caz,saz;
  cax=cos(aroundx*a); cay=cos(aroundy*a); caz=cos(aroundz*a);
  sax=sin(aroundx*a); say=sin(aroundy*a); saz=sin(aroundz*a);
  rotatenormals(o[obj].h[g].dx,o[obj].h[g].dy,o[obj].h[g].dz,cax,sax,cay,say,caz,saz);
  rotatedddwarestyle(&o[obj].h[g].rx,&o[obj].h[g].ry,&o[obj].h[g].rz,o[obj].h[g].dx[0],o[obj].h[g].dy[0],o[obj].h[g].dz[0],o[obj].h[g].dx[2],o[obj].h[g].dy[2],o[obj].h[g].dz[2]);
}
void  spinobject(int obj, float cx,float cy,float cz, float aroundx,float aroundy,float aroundz, int free)
{
  int g;
  float cax,sax,cay,say,caz,saz;
  cax=cos(aroundx*a); cay=cos(aroundy*a); caz=cos(aroundz*a);
  sax=sin(aroundx*a); say=sin(aroundy*a); saz=sin(aroundz*a);
  for (g=0; g<o[obj].turrets; g++)
  {
    rotatesummatelse(&o[obj].t[g].cx,&o[obj].t[g].cy,&o[obj].t[g].cz,cax,sax,cay,say,caz,saz);
    rotatesummatelse(&o[obj].t[g].sx,&o[obj].t[g].sy,&o[obj].t[g].sz,cax,sax,cay,say,caz,saz);
    rotatesummatelse(&o[obj].t[g].sx2,&o[obj].t[g].sy2,&o[obj].t[g].sz2,cax,sax,cay,say,caz,saz);
    rotatenormals(o[obj].t[g].dx,o[obj].t[g].dy,o[obj].t[g].dz,cax,sax,cay,say,caz,saz);
    rotatedddwarestyle(&o[obj].t[g].rx,&o[obj].t[g].ry,&o[obj].t[g].rz,o[obj].t[g].dx[0],o[obj].t[g].dy[0],o[obj].t[g].dz[0],o[obj].t[g].dx[2],o[obj].t[g].dy[2],o[obj].t[g].dz[2]);
//    rotatedddwarestyle(&o[obj].t[g].srx,&o[obj].t[g].sry,&o[obj].t[g].srz,o[obj].t[g].sx,o[obj].t[g].sy,o[obj].t[g].sz,o[obj].t[g].sx,o[obj].t[g].sy,o[obj].t[g].sz);
    rotatedddwarestyle(&o[obj].t[g].srx,&o[obj].t[g].sry,&o[obj].t[g].srz,o[obj].t[g].sx,o[obj].t[g].sy,o[obj].t[g].sz,o[obj].t[g].sx2,o[obj].t[g].sy2,o[obj].t[g].sz2);
  } // End of if there are turrets
  for (g=0; g<o[obj].hangerzones; g++)
  {
    rotatesummatelse(&o[obj].h[g].cx,&o[obj].h[g].cy,&o[obj].h[g].cz,cax,sax,cay,say,caz,saz);
    rotatenormals(o[obj].h[g].dx,o[obj].h[g].dy,o[obj].h[g].dz,cax,sax,cay,say,caz,saz);
    rotatedddwarestyle(&o[obj].h[g].rx,&o[obj].h[g].ry,&o[obj].h[g].rz,o[obj].h[g].dx[0],o[obj].h[g].dy[0],o[obj].h[g].dz[0],o[obj].h[g].dx[2],o[obj].h[g].dy[2],o[obj].h[g].dz[2]);
  } // End of if there are hangers
  rotatenormals(o[obj].dx,o[obj].dy,o[obj].dz,cax,sax,cay,say,caz,saz);
  rotatedddwarestyle(&o[obj].rx,&o[obj].ry,&o[obj].rz,o[obj].dx[0],o[obj].dy[0],o[obj].dz[0],o[obj].dx[2],o[obj].dy[2],o[obj].dz[2]);
  if(free==0 || free==2) rotatesummatelse(&o[obj].sx,&o[obj].sy,&o[obj].sz,cax,sax,cay,say,caz,saz);
  if(free!=2) rotatesummatelse(&o[obj].rsx,&o[obj].rsy,&o[obj].rsz,cax,sax,cay,say,caz,saz);
  o[obj].cx=o[obj].cx-cx;
  o[obj].cy=o[obj].cy-cy;
  o[obj].cz=o[obj].cz-cz;
  rotatesummatelse(&o[obj].cx,&o[obj].cy,&o[obj].cz,cax,sax,cay,say,caz,saz);
  o[obj].cx=o[obj].cx+cx;
  o[obj].cy=o[obj].cy+cy;
  o[obj].cz=o[obj].cz+cz;
}

void  spinprojectile(int obj, float cx,float cy,float cz, float aroundx,float aroundy,float aroundz, int free)
{
  float cax,sax,cay,say,caz,saz;
  cax=cos(aroundx*a); cay=cos(aroundy*a); caz=cos(aroundz*a);
  sax=sin(aroundx*a); say=sin(aroundy*a); saz=sin(aroundz*a);
  if (p[obj].type!=ION && p[obj].type!=120 && p[obj].type!=121 && p[obj].type<200)
  {
    rotatenormals(p[obj].dx,p[obj].dy,p[obj].dz,cax,sax,cay,say,caz,saz);
    rotatedddwarestyle(&p[obj].rx,&p[obj].ry,&p[obj].rz,p[obj].dx[0],p[obj].dy[0],p[obj].dz[0],p[obj].dx[2],p[obj].dy[2],p[obj].dz[2]);
  }
  if (free==0) rotatesummatelse(&p[obj].sx,&p[obj].sy,&p[obj].sz,cax,sax,cay,say,caz,saz);
  p[obj].cx=p[obj].cx-cx;
  p[obj].cy=p[obj].cy-cy;
  p[obj].cz=p[obj].cz-cz;
  rotatesummatelse(&p[obj].cx,&p[obj].cy,&p[obj].cz,cax,sax,cay,say,caz,saz);
  p[obj].cx=p[obj].cx+cx;
  p[obj].cy=p[obj].cy+cy;
  p[obj].cz=p[obj].cz+cz;
}

void  spindebris(int obj, float cx,float cy,float cz, float aroundx,float aroundy,float aroundz)
{
  float cax,sax,cay,say,caz,saz;
  cax=cos(aroundx*a); cay=cos(aroundy*a); caz=cos(aroundz*a);
  sax=sin(aroundx*a); say=sin(aroundy*a); saz=sin(aroundz*a);
  rotatenormals(d[obj].dx,d[obj].dy,d[obj].dz,cax,sax,cay,say,caz,saz);
  rotatedddwarestyle(&d[obj].rx,&d[obj].ry,&d[obj].rz,d[obj].dx[0],d[obj].dy[0],d[obj].dz[0],d[obj].dx[2],d[obj].dy[2],d[obj].dz[2]);
  d[obj].x=d[obj].x-cx;
  d[obj].y=d[obj].y-cy;
  d[obj].z=d[obj].z-cz;
  rotatesummatelse(&d[obj].x,&d[obj].y,&d[obj].z,cax,sax,cay,say,caz,saz);
  d[obj].x=d[obj].x+cx;
  d[obj].y=d[obj].y+cy;
  d[obj].z=d[obj].z+cz;
}

void  spincreateobjects(int obj, float cx,float cy,float cz, float aroundx,float aroundy,float aroundz )
{
  float cax,sax,cay,say,caz,saz;
  cax=cos(aroundx*a); cay=cos(aroundy*a); caz=cos(aroundz*a);
  sax=sin(aroundx*a); say=sin(aroundy*a); saz=sin(aroundz*a);
  rotatenormals(co[obj].dx,co[obj].dy,co[obj].dz,cax,sax,cay,say,caz,saz);
  rotatesummatelse(&co[obj].rsx,&co[obj].rsy,&co[obj].rsz,cax,sax,cay,say,caz,saz);
  co[obj].cx=co[obj].cx-cx;
  co[obj].cy=co[obj].cy-cy;
  co[obj].cz=co[obj].cz-(o[0].speed*velconst)-cz;
  rotatesummatelse(&co[obj].cx,&co[obj].cy,&co[obj].cz,cax,sax,cay,say,caz,saz);
  co[obj].cx=co[obj].cx+cx;
  co[obj].cy=co[obj].cy+cy;
  co[obj].cz=co[obj].cz+cz;
}

void spinguiobject(int obj, float cx,float cy,float cz, float aroundx,float aroundy,float aroundz, int free)
{
  float cax,sax,cay,say,caz,saz;

  cax=cos(aroundx*a); cay=cos(aroundy*a); caz=cos(aroundz*a);
  sax=sin(aroundx*a); say=sin(aroundy*a); saz=sin(aroundz*a);
  if (gui[obj].type!=ION && gui[obj].type!=120 && gui[obj].type!=121 && gui[obj].type<200)
  {
    rotatenormals(gui[obj].dx,gui[obj].dy,gui[obj].dz,cax,sax,cay,say,caz,saz);
    rotatedddwarestyle(&gui[obj].rx,&gui[obj].ry,&gui[obj].rz,gui[obj].dx[0],gui[obj].dy[0],gui[obj].dz[0],gui[obj].dx[2],gui[obj].dy[2],gui[obj].dz[2]);
  }
  if (free==0) rotatesummatelse(&gui[obj].sx,&gui[obj].sy,&gui[obj].sz,cax,sax,cay,say,caz,saz);
  gui[obj].cx=gui[obj].cx-cx;
  gui[obj].cy=gui[obj].cy-cy;
  gui[obj].cz=gui[obj].cz-cz;
  rotatesummatelse(&gui[obj].cx,&gui[obj].cy,&gui[obj].cz,cax,sax,cay,say,caz,saz);
  gui[obj].cx=gui[obj].cx+cx;
  gui[obj].cy=gui[obj].cy+cy;
  gui[obj].cz=gui[obj].cz+cz;
}

void  spinground(int obj, float cx,float cy,float cz, float aroundx,float aroundy,float aroundz)
{
  float cax,sax,cay,say,caz,saz;
  cax=cos(aroundx*a); cay=cos(aroundy*a); caz=cos(aroundz*a);
  sax=sin(aroundx*a); say=sin(aroundy*a); saz=sin(aroundz*a);
  rotatenormals(gr[obj].dx,gr[obj].dy,gr[obj].dz,cax,sax,cay,say,caz,saz);
  rotatedddwarestyle(&gr[obj].rx,&gr[obj].ry,&gr[obj].rz,gr[obj].dx[0],gr[obj].dy[0],gr[obj].dz[0],gr[obj].dx[2],gr[obj].dy[2],gr[obj].dz[2]);
  gr[obj].cx=gr[obj].cx-cx;
  gr[obj].cy=gr[obj].cy-cy;
  gr[obj].cz=gr[obj].cz-cz;
  rotatesummatelse(&gr[obj].cx,&gr[obj].cy,&gr[obj].cz,cax,sax,cay,say,caz,saz);
  gr[obj].cx=gr[obj].cx+cx;
  gr[obj].cy=gr[obj].cy+cy;
  gr[obj].cz=gr[obj].cz+cz;
}