/* 3 - D - Rotationsdemo      */
/* ---------------------------*/
/* benötigt mathtrans.library */
/* ---------------------------*/
/* Thomas Globisch            */
/*----------------------------*/

#include <math.h>
#include <libraries/mathffp.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/rastport.h>
#include <graphics/view.h>
#include <graphics/display.h>
#include <functions.h>

#define eckenzahl  40
#define linienzahl 52
#define XAchse 160
#define YAchse 100

struct GfxBase *GfxBase;
struct RastPort rp,rp2;
struct View view, *oldview;
struct ViewPort VP;
struct BitMap Bitmap,Bitmap2;
struct RasInfo ri;

int PaX[41] = { 0,-40,-55,-55,-40,-40,-55,-55,-40, 40, 55, 55, 40, 40, 55, 55,
               40,-55,-55,-55,-55, 55, 55, 55, 55, 10, 20, 20, 10,-10,-20,-20,
              -10, 10, 20, 20, 10,-10,-20,-20,-10 };
int PaY[41] = { 0, 40, 15,-15,-40, 40, 15,-15,-40, 40, 15,-15,-40, 40, 15,
              -15,-40,  2,  2, -2, -2,  2,  2, -2, -2, 20, 10,-10,-20,-20,
              -10, 10, 20, 20, 10,-10,-20,-20,-10, 10,20 };
int PaZ[41] = { 0,20,20,20,20,-20,-20,-20,-20,20,20,20,20,-20,-20,-20,-20,2,
               -2,2,-2,2,-2,2,-2,25,25,25,25,25,25,25,25,-25,-25,-25,-25,
              -25,-25,-25,-25 }; 

int PbX[41],PbY[41],PbZ[41];
int PcX[41],PcY[41],PcZ[41];
short verba[53] = {0,1,2,3,4,5,6,7,5,2,3,9,10,11,12,13,14,15,9,10,11,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,25,26,27,28,29,30,31,32};
short verbb[53] = {0,2,3,4,8,6,7,8,1,6,7,10,11,12,16,14,15,16,13,14,15,18,19,20,17,22,23,24,21,26,27,28,29,30,31,32,25,34,35,36,37,38,39,40,33,33,34,35,36,37,38,39,40};
int sinus[361],cosinus[361];
int perspektive[301];
int xgrad = 0, ygrad = 0, zgrad = 0;

main()
{
 static short map[2] = { 0x0000, 0x0FFF };

 GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L);

 oldview = GfxBase -> ActiView;
 InitView(&view);
 InitVPort(&VP);
 view.ViewPort = &VP;

 InitBitMap(&Bitmap ,1L,320L,200L);
 InitBitMap(&Bitmap2,1L,320L,200L);
 InitRastPort(&rp);
 InitRastPort(&rp2);

 rp.BitMap  = &Bitmap;
 rp2.BitMap = &Bitmap2;

 if((Bitmap.Planes[0] = AllocRaster(320L,200L)) == NULL) exit();
 BltClear(Bitmap.Planes[0],(long)RASSIZE(320L,200L),0L);

 if((Bitmap2.Planes[0] = AllocRaster(320L,200L)) == NULL) exit();
 BltClear(Bitmap2.Planes[0],(long)RASSIZE(320L,200L),0L);

 ri.BitMap = &Bitmap;
 ri.RxOffset = 0L;
 ri.RyOffset = 0L;
 ri.Next = NULL;

 VP.RasInfo  = &ri;
 VP.DWidth   = 320L;
 VP.DHeight  = 200L;
 VP.ColorMap = GetColorMap(2L);
 VP.Next     = NULL;

 LoadRGB4(&VP,&map,2L);

 MakeVPort(&view,&VP);
 MrgCop(&view);
 LoadView(&view);
 SetAPen(&rp, 1L);
 SetAPen(&rp2,1L);
 Move(&rp,38L,20L);
 Text(&rp,"3D - Echtzeit - Rotationsdemo",29L);
 Move(&rp,98L,180L);
 Text(&rp,"Thomas Globisch",15L);

 init();
 rotieren();
}

init()
{
 short lauf1;

 for (lauf1 = 0; lauf1 < 361;lauf1++)
 {
  sinus[lauf1]   =(int) (sin(lauf1*PI/180)*256);
  cosinus[lauf1] =(int) (cos(lauf1*PI/180)*256);
 }
 for(lauf1 = -150; lauf1 < 150; lauf1++)
   perspektive[lauf1+150] =(int) ( exp(lauf1 * log10(1.015)) * 256);
}

closestuff()
{
 FreeRaster(Bitmap.Planes[0],320L,200L);
 FreeRaster(Bitmap2.Planes[0],320L,200L);

 LoadView(oldview);
 CloseLibrary(GfxBase);
 exit();
}

rotieren()
{
 register short lauf,lauf3;

 for(;;)
 {
#asm
	btst	#6,$bfe001
	bne.s	ml
        jsr	_closestuff
ml
#endasm

   if((xgrad+=2)>360) xgrad -=360;
   if((ygrad+=5)>360) ygrad -=360;
   if((zgrad+=7)>360) zgrad -=360;


   for(lauf3 = 1; lauf3 <= eckenzahl;lauf3++)
   {
     PbX[lauf3] = ((cosinus[xgrad] * PaX[lauf3]) >> 8) - ((sinus[xgrad] * PaY[lauf3]) >> 8);
     PbY[lauf3] = ((cosinus[xgrad] * PaY[lauf3]) >> 8) + ((sinus[xgrad] * PaX[lauf3]) >> 8);

     PcX[lauf3] = ((cosinus[ygrad] * PbX[lauf3]) >> 8) - ((sinus[ygrad] * PaZ[lauf3]) >> 8);
     PbZ[lauf3] = ((cosinus[ygrad] * PaZ[lauf3]) >> 8) + ((sinus[ygrad] * PbX[lauf3]) >> 8);

     PcY[lauf3] = ((cosinus[zgrad] * PbY[lauf3]) >> 8) - ((sinus[zgrad] * PbZ[lauf3]) >> 8);
     PcZ[lauf3] = ((cosinus[zgrad] * PbZ[lauf3]) >> 8) + ((sinus[zgrad] * PbY[lauf3]) >> 8);

     PcX[lauf3] = (PcX[lauf3] * perspektive[PcZ[lauf3] + 150] >> 8) + XAchse;
     PcY[lauf3] = (PcY[lauf3] * perspektive[PcZ[lauf3] + 150] >> 8) + YAchse;
   }

   ClipBlit(&rp2,50L,30L,&rp2,50L,30L,220L,140L,(long) 0x40);
   for(lauf3 = 1;lauf3 <= linienzahl;lauf3++)
   {
     rp2.cp_x = PcX[verba[lauf3]];
     rp2.cp_y = PcY[verba[lauf3]];
     Draw(&rp2,(long) PcX[verbb[lauf3]],(long) PcY[verbb[lauf3]]);
   }
   WaitBOVP(&VP);
   ClipBlit(&rp2,50L,30L,&rp,50L,30L,220L,140L,(long) 0xc0);
 }
}
