#include "intlong.h"

bit16 clip(bit16 x1, bit16 y1, bit16 x2, bit16 y2, atomtype *ip);
bit32 divx(bit32 x);

atomtype imbuf[256];
atomtype *ibase1,*ibase2;
atomtype *iptr1,*iptr2;
atomtype *imax1,*imax2;
bit16 *pbase;
struct ptype {
        char state;
        bit16 trans[3];
        bit16 px,py;
        } points[20];
bit32 scprod();
extern bit16 view_pos[3];
extern bit16 view_vec[9];

void clear_image(void)
{
  ibase1 = imbuf;
  ibase2 = imbuf + 128;
  imax2 = ibase2;
}

void genxyz(bit16 p, bit16 *v, bit16 *r, bit16 *o)
{
  register struct ptype *pp = &points[p];
  if(pp->state == '0') {
    bit16 *qq;
    pp->state = '1';
    qq = &pbase[p * 3];
    pp->trans[0]=div14(mul16(v[0],qq[0])+mul16(v[3],qq[1])+mul16(v[6],qq[2]))
                -view_pos[0]+o[0];
    pp->trans[1]=div14(mul16(v[1],qq[0])+mul16(v[4],qq[1])+mul16(v[7],qq[2]))
                -view_pos[1]+o[1];
    pp->trans[2]=div14(mul16(v[2],qq[0])+mul16(v[5],qq[1])+mul16(v[8],qq[2]))
                -view_pos[2]+o[2];
/*    printf("qq %d,%d,%d\n",qq[0],qq[1],qq[2]);
    printf("ppt %d,%d,%d\n",pp->trans[0],pp->trans[1],pp->trans[2]); */
  }
  r[0] = pp->trans[0];
  r[1] = pp->trans[1];
  r[2] = pp->trans[2];
}

void gennorm(bit16 p, bit16 *v, bit16 *r)
{
  bit16 *qq = &pbase[p * 3];
  r[0]=div14(mul16(v[0],qq[0])+mul16(v[3],qq[1])+mul16(v[6],qq[2]));
  r[1]=div14(mul16(v[1],qq[0])+mul16(v[4],qq[1])+mul16(v[7],qq[2]));
  r[2]=div14(mul16(v[2],qq[0])+mul16(v[5],qq[1])+mul16(v[8],qq[2]));
}

void genxy(bit16 *v3, bit16 *v2)
{
  bit16 d = div14(scprod(v3,view_vec+3));
  v2[0] = (bit16)(divx(scprod(v3,view_vec)) / d) + (VPX1+VPX2)/2;
  v2[1] = (bit16)(divx(scprod(v3,view_vec+6)) / d) + (VPY1+VPY2)/2;
}

bit32 divx(bit32 x)
{
  return (x >> 6);
}

bit32 scprod(bit16 *v1, bit16 *v2)
{
  return mul16(v1[0],v2[0]) + mul16(v1[1],v2[1]) + mul16(v1[2],v2[2]);
}

void draw_body(bodytype *body)
{
  bit16 *b_data = body->shape;
  bit16 *fbase = b_data + 1;
  bit16 nface = fbase[0];
  bit16 *fptr = fbase + 1;
  bit16 *vbase = b_data + 1 + b_data[0];
  bit16 maxvec = vbase[-1];
  bit16 npoint;
  // bit16 flag;
  bit16 end_1[3],end_2[3];
  bit16 p[2],q[2];
  bit16 nvec,i,j;
  bit16 n_pos[3],n_vec[3];
  // bit16 *fptr2;
  char vec_done[20];
  pbase = vbase + vbase[-1]*2 + 1;
  npoint = pbase[-1];
  for(i=0; i<maxvec; i++) vec_done[i] = 0;
  for(i=0; i<npoint; i++) points[i].state = '0';
  for(i=nface; i != 0; i--) {
    nvec = *fptr++;
    gennorm(fptr[0],body->view,n_vec);
    genxyz(vbase[fptr[1]*2],body->view,n_pos,body->expos);
    if(scprod(n_pos,n_vec) < 0) {
      fptr++;
      for(j=0; j<nvec; j++) {
        if(!vec_done[fptr[0]]) {
          vec_done[fptr[0]] = 1;
          genxyz(vbase[fptr[0]*2],body->view,end_1,body->expos);
          genxyz(vbase[fptr[0]*2+1],body->view,end_2,body->expos);
          genxy(end_1,p);
          genxy(end_2,q);
          if(clip(p[0],p[1],q[0],q[1],iptr1)) iptr1++;
        }
        fptr++;
      } /* for j */
    } else {
      fptr += nvec + 1;
    } /* if(scprod..) */
  } /* for i */
}

void draw_object(bodytype *body)
{
  bit16 d,x,y,pr;
  bit16 delta[3];
  delta[0] = body->expos[0] - view_pos[0];
  delta[1] = body->expos[1] - view_pos[1];
  delta[2] = body->expos[2] - view_pos[2];
  d = div14(scprod(&view_vec[3],delta));
  if(d > body->r + 10) {
    x = divx(scprod(&view_vec[0],delta) / d);
    y = divx(scprod(&view_vec[6],delta) / d);
    pr = divx(mul16(body->r,16384) / d);
    if((abs(x) < (VPX2-VPX1)/2 + pr) && (abs(y) < (VPY2-VPY1)/2 + pr)) {
      draw_body(body);
    }
  }
}

