/*  This program will display THREE dimensions on a TWO dimensional screen  */

#include <exec/types.h>
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfxbase.h>
#include <graphics/gfx.h>
#include <graphics/text.h>
#include <graphics/regions.h>
#include <graphics/copper.h>
#include <graphics/gels.h>
#include <devices/serial.h>
#include <devices/keymap.h>
#include <hardware/blit.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#ifdef LATTICE		/* Currently only Lattice has this */
#include <limits.h>
#endif

#define pi            3.141592654
#define INTUITION_REV 1
#define GRAPHICS_REV  1
#define MILLION       1000000
#define SX            320
#define SY            200

struct IntuitionBase *IntuitionBase;
struct GfxBase       *GfxBase;
struct Screen        *Screen;
struct Window        *Window;
struct IntuiMessage  *Message;

struct NewScreen NewScreen =
 {
    0,0,SX,SY,1,-1,-2,/* HIRES | LACE*/ NULL, CUSTOMSCREEN,
    NULL,NULL,NULL,NULL,
 };
struct NewWindow NewWindow =
 {
    0,00,SX,SY,-1,-1,
    CLOSEWINDOW | MOUSEMOVE | MOUSEBUTTONS,
    BACKDROP | BORDERLESS | WINDOWCLOSE,
    NULL,NULL,NULL,NULL,NULL,
    0,0,0,0,CUSTOMSCREEN,
 };

/* This is the data all the functions need to see */

#define TOP 50 /* 100 3d points maximum, change at will       */
#define WID 4   /* Width of the 3d matrix x,y,z, perspective   */
#define DEW 2   /* Width of display data  x,y                  */
#define PLA 3   /* THREE Planes in 3 dimensions                  */
#define SIZ 100 /* Size of each line of capture at maximum     */

static double thre [ WID ][ WID ];/* This matrix will contain the 3d formula */
static double deta [ TOP ][ WID ];/* This matrix will contain your data      */
         int disp [ TOP ][ WID ];/* Screen coords, note use of WID not DEW  */
static float rads [ PLA ]       ;/* Three rotation planes in three dimensions! */

/*********** RETRIEVE DATA FUNCTION ************/

retrieve (file)
char *file[];
{
     FILE *input;
     char buffer [ SIZ ],rec [ 20 ]; /* 80 chars on one line, 3 sets */
     int a,i,pos;
     pos = FALSE; /* if it stays false program will abort later */
                  /* else it will represent size of data        */

     if ((input = fopen(file,"r"))== NULL) goto HEAVEN;

     while ((fgets(buffer,SIZ,input)))
  {
          a = 0;
          for (i=0;i<WID;i++)
       {
               if (pos > TOP) goto HEAVEN;
               a = strcspn(buffer,",");
               strncpy (rec,buffer,a);
               deta [pos][i] = atof (rec);
               ++a;
               strcpy (buffer,buffer+a);
       }
     ++pos;
  }
HEAVEN:

     fclose (input);
     return (pos-1);
}

/*********** MULTIPLY DATA FUNCTION ************/

multiply (data,P1)
int data;
double P1;
{
    int c,r,i;
    float x,y,z;
    double tweedle;
    float Cz,Cy,Cx,Sz,Sy,Sx,Nz,Ny,Nx;

/* pull desired rotation radians out of array */
    x = rads [ 0 ];
    y = rads [ 1 ];
    z = rads [ 2 ];

    Cz=cos(z);Sz=sin(z);Nz=-sin(z);
    Cy=cos(y);Sy=sin(y);Ny=-sin(y);
    Cx=cos(x);Sx=sin(x);Nx=-sin(x);
    
    thre [0][0] = Cz*Cy;
    thre [0][1] = Sz*Cx+Cz*Sy*Nx;
    thre [0][2] = 0.0;
    thre [0][3] = (Sz*Sx+Cz*Sy*Cx)*P1;

    thre [1][0] = Nz*Cy;
    thre [1][1] = Cz*Cx+Nz*Sy*Nx;
    thre [1][2] = 0.0;
    thre [1][3] = (Cz*Sx+Nz*Sy*Cx)*P1;

    thre [2][0] = Ny;
    thre [2][1] = Cy*Nx;
    thre [2][2] = 0.0;
    thre [2][3] = Cy*Cx*P1;

    thre [3][0] = 0.0;
    thre [3][1] = 0.0;
    thre [3][2] = 0.0;
    thre [3][3] = 1.0;

/* Cross multipy transformation matrix agaist your points */

    for (r=0;r<data;r++)
 {
         for (c=0;c<WID;c++)
      {
              tweedle = 0.0;
              for (i=0;i<WID;i++)
           {

                   tweedle += (deta [r][i]) * (thre [i][c]);
           }
              disp [r][c] = ceil(tweedle);
      }
 }
return (TRUE);
}

main (argc,argv)
short argc;
char *argv[];

{

     double persx;
     short forever = TRUE;
     int x,y,pos,top,rot,i;

     short INTOPEN = FALSE,
           GFXOPEN = FALSE,
           SCNOPEN = FALSE,
           WINOPEN = FALSE,
           MENOPEN = FALSE;

     rads[0]=0.0;rads[1]=0.0;rads[2]=0.0;

     if (argc == 1) { printf("Please supply rotatation's. ex: 1> thre 7\n");exit();}

     rot = atoi(argv[1]);

     if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",INTUITION_REV)))
         goto HELL;INTOPEN = TRUE;

     if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV)))
         goto HELL;GFXOPEN = TRUE;

     if (!(Screen = (struct Screen *)OpenScreen(&NewScreen)))
         goto HELL;SCNOPEN = TRUE;

     ShowTitle(Screen,FALSE);
     NewWindow.Screen = Screen;

     if (!(Window = (struct Window *)OpenWindow(&NewWindow)))
         goto HELL;WINOPEN = TRUE;

/* Start of Program */

     if (!(top = retrieve ("thredata"))) goto HELL;

/* Main Program Loop */

    while (forever)
 {
        if (Message = (struct IntuiMessage *)GetMsg(Window->UserPort))
            if ((Message->Class == CLOSEWINDOW)) goto HELL;


    if ((rot & 1) > 0) rads[0] +=.1;if (rads[0]>pi)rads[0]=-pi;
    if ((rot & 2) > 0) rads[1] +=.1;if (rads[1]>pi)rads[1]=-pi;
    if ((rot & 4) > 0) rads[2] +=.1;if (rads[2]>pi)rads[2]=-pi;

    persx = 1.0;
    if (!(multiply (top,persx))) goto HELL;
    SetAPen  (Window->RPort,0);
    RectFill (Window->RPort,0,10,SX,SY);
    SetAPen  (Window->RPort,3);

    for (pos=0;pos<top;pos++)
  {
        x = disp [ pos ][ 0 ];
        y = disp [ pos ][ 1 ];
        x += SX/2;y += SY/2;

        if (pos == 0)
        Move (Window->RPort,x,y);

        Draw (Window->RPort,x,y);
  }
       
 }
HELL:

      if (MENOPEN)  ClearMenuStrip (Window);
      if (WINOPEN)  CloseWindow    (Window);
      if (SCNOPEN)  CloseScreen    (Screen);
      if (GFXOPEN)  CloseLibrary   (GfxBase);
      if (INTOPEN)  CloseLibrary   (IntuitionBase);
      exit (TRUE);
}
