home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 544b.lha / Tesseract / tess.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-06  |  24.6 KB  |  949 lines

  1. /* Tesseract   ©1991, Jerry D. Hedden, All Rights Reserved
  2.  
  3. The Tesseract program, source code, documenation, and icon imagery are
  4. freely redistributable, but may not be modified in any way, or used in part
  5. or in whole without the express written consent of the author.    Images
  6. generated by the Tesseract program may be used for any purpose provided
  7. credit is given to the program's author.
  8.  
  9.     Jerry D. Hedden
  10.     28 Windemere Dr.
  11.     Sicklerville, NJ  08081
  12.     Phone:    (609)629-3975
  13.     Email:    Hedden@ESDSDF.DNet.GE.com
  14.  
  15. ===========================================================================
  16.  
  17. This source code REQUIRES Aztec 'C' v3.6a.  It probably cannot be handled
  18. by any other compiler because of the assumed register usage within the
  19. embedded assembly code.  Make with the following:
  20.  
  21.     as startup
  22.     cc +x3 -e500 -z10000 tess
  23.     ln -m -o Tesseract startup.o tess.o -lc
  24.  
  25. ===========================================================================
  26.  
  27. The following copyright notice accompanied the source code for Palette
  28. Requester which was used as a model for this program's Color Requester.
  29.  
  30. Palette Requester -- (c) Copyright 1989 Jonathan Potter
  31. This program is freely redistributable, although all rights to it remain
  32. with the author. It may be used freely in any program as long as this
  33. notice remains intact, however, if you do this, please mention the author
  34. in the program.  If you wish to use this in a commercial program of any
  35. kind, you must register with a $15 donation.
  36. Please send donations, bug reports, comments and suggestions to :
  37.     Jonathan Potter
  38.     3 William Street
  39.     Clarence Park 5034
  40.     South Australia
  41.     Australia
  42.  
  43. ===========================================================================
  44.  
  45. History:
  46.  
  47. v1.00 - 10 Aug 1991
  48.   Initial release
  49.  
  50. **************************************************************************/
  51.  
  52. #include <intuition/intuition.h>
  53.  
  54. /* corrects <exec/memory.h> long integer problems */
  55. #define CLEARED_CHIP    0x00010002L
  56.  
  57. /* required libraries */
  58. struct Library    *IntuitionBase, *GfxBase, *MathBase, *MathTransBase,
  59.         *_OpenLibrary();
  60.  
  61. /* Motorola FFP math routines */
  62. long  SPFix(), SPTst();
  63. float SPFlt(), SPAdd(), SPSub(), SPMul();
  64. float SPSincos(), SPSqrt();
  65.  
  66. /* arrays for holding pre-computed, converted "floating point" values */
  67. short cos[720], sin[720];
  68.  
  69. /* circle constants */
  70. #define PI        (float)3.1415926535897932384626433832795
  71. #define HALF_DEG    (float)(PI/360.0)
  72.  
  73. /* rotation constants */
  74. #define RESTART        -1
  75. #define STOPPED     0
  76. #define TEN_DEGREES    20
  77. #define NINETY_DEGREES    180
  78. #define THREE_SIXTY    720
  79.  
  80. /* the 4 coordinates */
  81. #define X 0L
  82. #define Y 1L
  83. #define Z 2L
  84. #define W 3L
  85.  
  86. /* viewing angles */
  87. short cos_theta,sin_theta,cos_phi,sin_phi;
  88.  
  89. /* objects plotted by this program */
  90. #define TESSERACT 0
  91. short t4d[33][4], tseq[33] =
  92. {0,1,3,2,0,8,9,11,10,8,12,14,10,2,6,4,5,7,6,14,15,11,3,7,15,13,9,1,5,13,12,4,0};
  93.  
  94. #define OCTAHEDRON 1
  95. short o4d[25][4], oseq[25] =
  96. {0,2,1,3,0,4,1,5,2,4,3,5,0,6,1,7,2,6,3,7,4,6,5,7,0};
  97.  
  98. #define PYRAMID 2
  99. short p4d[11][4], pseq[11] = {0,1,2,3,4,1,3,0,2,4,0};
  100.  
  101. /* information for display and graphics */
  102. #define WIDTH        656L
  103. #define HEIGHT        430L
  104. #define PLANES        1
  105. #define PLANESIZE    (long)((WIDTH>>3)*HEIGHT)
  106. /* used in mapping to screen */
  107. #asm
  108. H_HEIGHT    equ    215
  109. H_WIDTH     equ    328
  110. ; SCALE_X = SCALE_Y * 7/8
  111. SCALE_X     equ    65
  112. SCALE_Y     equ    75
  113. #endasm
  114.  
  115. struct Screen *screen, *OpenScreen();
  116. struct ViewPort *vp;
  117. struct Window *window, *OpenWindow();
  118. struct RastPort *rp;
  119. short *pointer;
  120. struct IntuiMessage *_GetMsg();
  121. PLANEPTR buffer1[PLANES], buffer2[PLANES], _AllocMem();
  122.  
  123. struct NewScreen MyScreen = {
  124.   0,0, WIDTH,HEIGHT,PLANES, 0,1, HIRES|LACE,CUSTOMSCREEN,
  125.   NULL,(UBYTE *)"Tesseract",NULL,NULL
  126. };
  127.  
  128. struct NewWindow MyWindow = {
  129.   0,0, WIDTH,HEIGHT, 0,1, RAWKEY|MOUSEMOVE,
  130.   NOCAREREFRESH|BORDERLESS|ACTIVATE|SIMPLE_REFRESH|RMBTRAP|REPORTMOUSE,
  131.   NULL,NULL,NULL,NULL,NULL, WIDTH,HEIGHT, WIDTH,HEIGHT, CUSTOMSCREEN
  132. };
  133.  
  134. /* colors */
  135. #define BLACK    0L
  136. #define WHITE    1L
  137.  
  138. UWORD ColorTables[3][1<<PLANES] = {
  139.   {0x0000,0x0079},
  140.   {0x0FFF,0x0000},
  141.   /* used by color requester */
  142.   {0x0000,0x0079}
  143. };
  144.  
  145.  
  146. /* sets up the pre-computed, converted "floating point" arrays */
  147. Initialize()
  148. {
  149.   register long i;
  150.   register float fsin;
  151.   float fcos;
  152.  
  153.   initial_pos();
  154.  
  155.   for (i=0; i<720; i++) {
  156.     fsin = SPSincos(&fcos,SPMul(HALF_DEG,SPFlt(i)));
  157.     cos[i] = (SPTst(fcos) >= 0) ? SPFix(SPAdd(0.5,SPMul(fcos,8192.0))) :
  158.                   SPFix(SPSub(0.5,SPMul(fcos,8192.0)));
  159.     sin[i] = (SPTst(fsin) >= 0) ? SPFix(SPAdd(0.5,SPMul(fsin,8192.0))) :
  160.                   SPFix(SPSub(0.5,SPMul(fsin,8192.0)));
  161.   }
  162. }
  163.  
  164.  
  165. #define SCALE_O 14500
  166. #define SCALE_P 3000.0
  167.  
  168. /* sets the objects to their "starting positions" */
  169. initial_pos()
  170. {
  171.   register long i;
  172.  
  173.   for (i=0; i<33; i++) {
  174.     t4d[i][X] = (((tseq[i]<<1)&2)-1)<<13;
  175.     t4d[i][Y] = (((tseq[i]   )&2)-1)<<13;
  176.     t4d[i][Z] = (((tseq[i]>>1)&2)-1)<<13;
  177.     t4d[i][W] = (((tseq[i]>>2)&2)-1)<<13;
  178.   }
  179.   for (i=0; i<25; i++) {
  180.     o4d[i][X] = (oseq[i]==0 || oseq[i]==1) ? ((oseq[i]&1) ? SCALE_O : -SCALE_O) : 0;
  181.     o4d[i][Y] = (oseq[i]==2 || oseq[i]==3) ? ((oseq[i]&1) ? SCALE_O : -SCALE_O) : 0;
  182.     o4d[i][Z] = (oseq[i]==4 || oseq[i]==5) ? ((oseq[i]&1) ? SCALE_O : -SCALE_O) : 0;
  183.     o4d[i][W] = (oseq[i]==6 || oseq[i]==7) ? ((oseq[i]&1) ? SCALE_O : -SCALE_O) : 0;
  184.   }
  185.   for (i=0; i<11; i++) {
  186.     p4d[i][X] = (pseq[i] < 2) ? ((pseq[i] == 1) ?
  187.             SPFix(SPMul(SCALE_P,SPMul( 3.0,SPSqrt(2.0)))) :
  188.             SPFix(SPMul(SCALE_P,SPMul(-3.0,SPSqrt(2.0)))) ) : 0;
  189.     p4d[i][Y] = (pseq[i] < 3) ? ((pseq[i] == 2) ?
  190.             SPFix(SPMul(SCALE_P,SPMul( 2.0,SPSqrt(6.0)))) :
  191.             SPFix(SPMul(SCALE_P,SPMul(-1.0,SPSqrt(6.0)))) ) : 0;
  192.     p4d[i][Z] = (pseq[i] < 4) ? ((pseq[i] == 3) ?
  193.             SPFix(SPMul(SCALE_P,SPMul( 3.0,SPSqrt(3.0)))) :
  194.             SPFix(SPMul(SCALE_P,SPMul(-1.0,SPSqrt(3.0)))) ) : 0;
  195.     p4d[i][W] =          (pseq[i] == 4) ?
  196.             SPFix(SPMul(SCALE_P,SPMul( 2.4,SPSqrt(5.0)))) :
  197.             SPFix(SPMul(SCALE_P,SPMul(-0.6,SPSqrt(5.0))))  ;
  198.   }
  199. }
  200.  
  201.  
  202. /* rotates the four-dimensional objects */
  203. rotate_4d(dir1,dir2,angle)
  204. long dir1,dir2;
  205. short angle;
  206. {
  207.   register short cangle, sangle;
  208.   register short *rega2, *rega3;
  209.   register long i;
  210.  
  211.   if (angle == RESTART)  {
  212.     initial_pos();
  213.     return;
  214.   }
  215.  
  216.   cangle = cos[angle];    sangle = sin[angle];
  217.  
  218.   rega2 = &t4d[0][dir1];  rega3 = &t4d[0][dir2];
  219.   for (i=0; i<33; i++) {
  220. #asm
  221.     bsr.s    rotate
  222. #endasm
  223.   }
  224.  
  225.   rega2 = &o4d[0][dir1];  rega3 = &o4d[0][dir2];
  226.   for (i=0; i<25; i++) {
  227. #asm
  228.     bsr.s    rotate
  229. #endasm
  230.   }
  231.  
  232.   rega2 = &p4d[0][dir1];  rega3 = &p4d[0][dir2];
  233.   for (i=0; i<11; i++) {
  234. #asm
  235.     bsr.s    rotate
  236. #endasm
  237.   }
  238.   return;
  239.  
  240. #asm
  241. rotate: move.w    (a2),d0 ; d1' = d1*cos - d2*sin
  242.     muls    d4,d0
  243.     move.w    (a3),d2
  244.     muls    d5,d2
  245.     sub.l    d2,d0
  246.     move.w    (a2),d1 ; d2' = d1*sin + d2*cos
  247.     muls    d5,d1
  248.     move.w    (a3),d2
  249.     muls    d4,d2
  250.     add.l    d2,d1
  251.     moveq    #13,d3    ; normalize
  252.     asr.l    d3,d0
  253.     asr.l    d3,d1
  254.     move.w    d0,(a2)
  255.     move.w    d1,(a3)
  256.     addq.l    #8,a2
  257.     addq.l    #8,a3
  258.     rts
  259. #endasm
  260. }
  261.  
  262.  
  263. plot_object(object)
  264. short object;
  265. {
  266.   register long i, size;
  267.   short plot_buf[66];
  268.   register short *obj_ptr, *buf_ptr = plot_buf;
  269.  
  270.   if (object == TESSERACT) {
  271.     obj_ptr = &t4d[0][X];  size = 33;
  272.   } else if (object == OCTAHEDRON) {
  273.     obj_ptr = &o4d[0][X];  size = 25;
  274.   } else {  /* PYRAMID */
  275.     obj_ptr = &p4d[0][X];  size = 11;
  276.   }
  277.  
  278.   for (i=0; i<size; i++) {
  279. #asm
  280.     move.w    (a2),d0         ; x' = x*cos_theta - z*sin_theta
  281.     muls    _cos_theta,d0
  282.     move.w    4(a2),d2
  283.     muls    _sin_theta,d2
  284.     sub.l    d2,d0
  285.  
  286.     move.w    (a2),d1         ; z' = x*sin_theta + z*cos_theta
  287.     muls    _sin_theta,d1
  288.     move.w    4(a2),d2
  289.     muls    _cos_theta,d2
  290.     add.l    d2,d1
  291.  
  292.     moveq    #13,d3        ; normalize z'
  293.     asr.l    d3,d1
  294.  
  295.     move.w    2(a2),d2        ; y' = y*cos_phi - z'*sin_phi
  296.     muls    _cos_phi,d2
  297.     muls    _sin_phi,d1
  298.     sub.l    d1,d2
  299.  
  300.     asr.l    d3,d0        ; normalize x' and y'
  301.     asr.l    d3,d2
  302.  
  303.     divs    #SCALE_X,d0    ; screen_x = WIDTH/2 + x'/SCALE_X
  304.     add.w    #H_WIDTH,d0
  305.     divs    #-SCALE_Y,d2    ; screen_y = HEIGHT/2 - y'/SCALE_Y
  306.     add.w    #H_HEIGHT,d2
  307.  
  308.     move.w    d0,(a3)+        ; store in plotting buffer
  309.     move.w    d2,(a3)+
  310.     addq.l    #8,a2        ; move to next point
  311. #endasm
  312.   }
  313.  
  314.   SetBuffer();
  315.   Move(rp,(long)plot_buf[0],(long)plot_buf[1]);
  316.   PolyDraw(rp,size,plot_buf);
  317.   DisplayBuffer();
  318. }
  319.  
  320.  
  321. /* for double buffering */
  322. SetBuffer()
  323. {
  324.   register long i;
  325.  
  326.   if (rp->BitMap->Planes[0] == buffer1[0])
  327.     for (i=0; i<PLANES; i++)
  328.       rp->BitMap->Planes[i] = buffer2[i];
  329.   else
  330.     for (i=0; i<PLANES; i++)
  331.       rp->BitMap->Planes[i] = buffer1[i];
  332.   SetRast(rp,BLACK);
  333. }
  334.  
  335.  
  336. DisplayBuffer()
  337. {
  338.   WaitBOVP(vp);
  339.   WaitTOF();
  340.   ScrollVPort(vp);
  341.   RethinkDisplay();
  342. }
  343.  
  344.  
  345. #define ONE_KEY     1
  346. #define ZERO_KEY    10
  347. #define ESCAPE        69
  348. #define SPACE        64
  349. #define RKEY        19
  350. #define TKEY        20
  351. #define IKEY        23
  352. #define OKEY        24
  353. #define PKEY        25
  354. #define DKEY        34
  355. #define XKEY        50
  356. #define CKEY        51
  357. #define KP8        62
  358. #define KP2        30
  359. #define KP4        45
  360. #define KP6        47
  361. #define UPARROW     76
  362. #define DOWNARROW    77
  363. #define LEFTARROW    79
  364. #define RIGHTARROW    78
  365. #define HELP        95
  366.  
  367. #define IMAGINARY    0
  368. #define REAL        1
  369.  
  370. #define STILL        0
  371. #define MOVED        1
  372.  
  373. MainLoop()
  374. {
  375.   register struct IntuiMessage *msg;
  376.   register ULONG class;
  377.   register USHORT code;
  378.   register USHORT qualifier;
  379.   register short mouse = MOVED;
  380.   short plot_it, mode;
  381.   short object      = TESSERACT;
  382.   short step_rate = 5;
  383.   short ColorSet  = BLACK;
  384.  
  385.   struct {
  386.     long axis1, axis2;
  387.     short angle;
  388.   } rot[2];
  389.  
  390.   Initialize();
  391.   goto reset;
  392.  
  393.   for (;;) {
  394.     if (rot[0].angle != STOPPED) {
  395.       rotate_4d(rot[0].axis1,rot[0].axis2,rot[0].angle);
  396.       if (rot[0].angle != step_rate  &&  rot[0].angle != THREE_SIXTY-step_rate)
  397.     rot[0].angle = STOPPED;
  398.       else if (rot[1].angle != STOPPED)
  399.     rotate_4d(rot[1].axis1,rot[1].axis2,rot[1].angle);
  400.       plot_it = TRUE;
  401.     }
  402.     if (plot_it) {
  403.       plot_object(object);
  404.       plot_it = FALSE;
  405.     }
  406.     if (rot[0].angle == STOPPED)
  407.       _WaitPort(window->UserPort);
  408.     while (msg = _GetMsg(window->UserPort)) {
  409.       class  = msg->Class;   code   = msg->Code;    qualifier = msg->Qualifier;
  410.       _ReplyMsg(msg);
  411.       if (class == MOUSEMOVE) {
  412.     mouse = MOVED;
  413.       } else if (class == RAWKEY) {
  414.     switch (code) {
  415.       case TKEY:
  416.         object = TESSERACT;  plot_it = TRUE;
  417.         break;
  418.       case OKEY:
  419.         object = OCTAHEDRON;  plot_it = TRUE;
  420.         break;
  421.       case PKEY:
  422.         object = PYRAMID;  plot_it = TRUE;
  423.         break;
  424.       case RKEY:
  425.         mode = REAL;
  426.         break;
  427.       case IKEY:
  428.         mode = IMAGINARY;
  429.         break;
  430.       case DKEY:
  431.         if (qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) {
  432.           rot[1].angle = STOPPED;
  433.         } else {
  434.           rot[1] = rot[0];
  435.           rot[0].angle = STOPPED;
  436.         }
  437.         break;
  438.       case XKEY:
  439. reset:
  440.         mode = REAL;
  441.         rot[0].axis1 = X;  rot[0].axis2 = Z;  rot[0].angle = RESTART;
  442.         rot[1].angle = STOPPED;
  443.         plot_it = TRUE;
  444.         break;
  445.       case CKEY:
  446.         if (qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) {
  447.           ColorRequester(ColorSet);
  448.           plot_it = TRUE;
  449.         } else {
  450.           if (ColorSet = 1 - ColorSet)
  451.         SetRGB4(vp,17L,0L,0L,0L);
  452.           else
  453.         SetRGB4(vp,17L,15L,15L,15L);
  454.           LoadRGB4(vp, &ColorTables[ColorSet][0], 1L<<PLANES);
  455.         }
  456.         break;
  457.       case SPACE:
  458.         rot[0].angle = STOPPED;
  459.         break;
  460.       case KP4:
  461.       case KP6:
  462.         rot[0].axis1 = X;  rot[0].axis2 = (mode) ? Z : W;
  463.         goto calc_angle;
  464.       case KP8:
  465.       case KP2:
  466.         rot[0].axis1 = Y;  rot[0].axis2 = (mode) ? Z : W;
  467.         goto calc_angle;
  468.       case LEFTARROW:
  469.       case RIGHTARROW:
  470.         mode = REAL;  rot[0].axis1 = X;  rot[0].axis2 = Y;
  471.         goto calc_angle;
  472.       case UPARROW:
  473.       case DOWNARROW:
  474.         mode = IMAGINARY;  rot[0].axis1 = Z;  rot[0].axis2 = W;
  475. calc_angle:
  476.         if (qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  477.           rot[0].angle = TEN_DEGREES;
  478.         else if (qualifier & IEQUALIFIER_CONTROL)
  479.           rot[0].angle = NINETY_DEGREES;
  480.         else
  481.           rot[0].angle = step_rate;
  482.         if (code == KP8  ||  code == RIGHTARROW  ||
  483.         code == KP6  ||  code == UPARROW)
  484.           rot[0].angle = THREE_SIXTY - rot[0].angle;
  485.         break;
  486.       case ESCAPE:
  487.         cleanup(0L);
  488.       case HELP:
  489.         LoadRGB4(vp, &ColorTables[0][0], 1L<<PLANES);
  490.         info();
  491.         LoadRGB4(vp, &ColorTables[ColorSet][0], 1L<<PLANES);
  492.         plot_it = TRUE;
  493.         break;
  494.       default:
  495.         if (code >= ONE_KEY  &&  code <= ZERO_KEY) {
  496.           if (rot[0].angle != STOPPED)
  497.         if (rot[0].angle == step_rate)
  498.           rot[0].angle = code;
  499.         else
  500.           rot[0].angle = THREE_SIXTY - code;
  501.           step_rate = code;
  502.         }
  503.     }
  504.       }
  505.     }
  506.     if (mouse) {
  507.       short x,y;
  508.       x = (screen->MouseX*45)/41;  /* CAUTION: these factors are  */
  509.       y = (screen->MouseY*36)/43;  /*    highly screen-dependent  */
  510.       if (x > 719)  x = 719;
  511.       cos_theta = (-cos[x]);  sin_theta =   sin[x];
  512.       cos_phi    =   sin[y];   sin_phi    = (-cos[y]);
  513.       mouse = STILL;  plot_it = TRUE;
  514.     }
  515.   }
  516. }
  517.  
  518.  
  519. main()
  520. {
  521.   long i;
  522.  
  523.   if (IntuitionBase = _OpenLibrary("intuition.library", 0L))
  524.   if (GfxBase       = _OpenLibrary("graphics.library", 0L))
  525.   if (MathBase      = _OpenLibrary("mathffp.library", 0L))
  526.   if (MathTransBase = _OpenLibrary("mathtrans.library", 0L))
  527.   if (screen = OpenScreen(&MyScreen)) {
  528.     vp = &screen->ViewPort;
  529.     LoadRGB4(vp,&ColorTables[0][0],1L<<PLANES);
  530.     MyWindow.Screen = screen;
  531.   if (window = OpenWindow(&MyWindow)) {
  532.     rp = window->RPort;
  533.     SetDrMd(rp,(long)JAM1);
  534.     SetAPen(rp,WHITE);
  535.     for (i=0; i<PLANES; i++) {
  536.       buffer1[i] = rp->BitMap->Planes[i];
  537.       if (!(buffer2[i] = _AllocMem(PLANESIZE,CLEARED_CHIP)))
  538.     cleanup(101L);
  539.     }
  540.   if (pointer = (short *)_AllocMem(16L,CLEARED_CHIP))
  541.     /* set a white one-pixel pointer */
  542.     pointer[2] = 0x8000;
  543.     SetRGB4(vp,17L,15L,15L,15L);
  544.     SetPointer(window,pointer,1L,1L,0L,0L);
  545.     MainLoop();   /* terminates via cleanup() */
  546.   }
  547.   }
  548.   cleanup(100L);  /* no direct indication of what went wrong above */
  549. }
  550.  
  551.  
  552. cleanup(code)
  553. long code;
  554. {
  555.   long i;
  556.  
  557.   if (pointer) {
  558.     ClearPointer(window);
  559.     _FreeMem(pointer,16L);
  560.   }
  561.   if (window) {
  562.     if (rp->BitMap->Planes[0] == buffer2[0]) {
  563.       SetBuffer();
  564.       DisplayBuffer();
  565.     }
  566.     CloseWindow(window);
  567.   }
  568.   for (i=0; i<PLANES; i++)
  569.     if (buffer2[i])     _FreeMem(buffer2[i],PLANESIZE);
  570.   if (screen)           CloseScreen(screen);
  571.   if (MathTransBase)    _CloseLibrary(MathTransBase);
  572.   if (MathBase)         _CloseLibrary(MathBase);
  573.   if (GfxBase)          _CloseLibrary(GfxBase);
  574.   if (IntuitionBase)    _CloseLibrary(IntuitionBase);
  575.   exit(code);
  576. }
  577.  
  578.  
  579. /*** Info function ***/
  580.  
  581. struct TextAttr InfoFont =
  582.   {(UBYTE *)"topaz.font",8,FS_NORMAL,FPF_ROMFONT|FPF_DESIGNED};
  583. struct IntuiText Text = {1,0,JAM2,0,0,&InfoFont,NULL,NULL};
  584.  
  585. #define TEXT_MARGIN    14L
  586. #define TEXT_START    22L
  587.  
  588. char *InfoTitle  =
  589.     " Tesseract v1.00    \2511991, Jerry D. Hedden, All Rights Reserved";
  590. char *InfoText[] = {
  591. "You are viewing the three-dimensional projection of a four-dimensional object.",
  592. "You can select amoung the objects supported by this program by pressing 't'",
  593. "for the tesseract (a hyper-cube), 'o' for a hyper-octahedron or 'p' for a",
  594. "hyper-tetrahedron (think [incorrectly] of a pyramid).  To quit, press 'esc'.",
  595. "",
  596. "With the mouse pointer in the center of the screen, the x-axis is horizontal",
  597. "to the screen, y is vertical, and z extends outward.  (The fourth-dimensional",
  598. "w-axis cannot be 'seen', of course.)  The mouse moves these axes; allowing",
  599. "views of the object from any angle.",
  600. "",
  601. "You can rotate the object in four-dimensional space using the arrow and keypad",
  602. "keys.  Rotations in the x-y, x-z and y-z planes are referred to as REAL",
  603. "because they result in rotations of the object in 3D.  For the x-w, y-w and",
  604. "z-w planes, rotations are IMAGINARY; occuring only in four-dimensional space.",
  605. "The keypad 8, 2, 4 and 6 represent the up, down, left and right directions.",
  606. "Pressing 'r' sets the keypad to perform REAL rotations on the object; 'i' sets",
  607. "IMAGINARY rotations.  These correspond to rotations in the x-z plane (REAL",
  608. "4/6), y-z plane (REAL 8/2), x-w plane (IMAGINARY 4/6) and y-w plane (IMAGINARY",
  609. "8/2).  The left/right arrows perform REAL rotations counterclockwise/clockwise",
  610. "in x-y plane.  The up/down arrows perform IMAGINARY rotations in the z-w plane.",
  611. "",
  612. "Pressing an arrow/keypad key alone causes its action to repeat continuously.",
  613. "Press 'space' to stop.  The change between frames can be set from 0.5\260 to 5\260",
  614. "using the keyboard 1 thru 0.  'Shift-' arrow/keypad keys cause a single 10\260",
  615. "change; 'ctrl-' causes a 90\260 change.",
  616. "",
  617. "The object can be rotated in two planes at once.  Set up a rotation, either",
  618. "REAL or IMAGINARY and at the desired rate, and press 'd' (for dual).  The",
  619. "object will stop which indicates that the settings have been entered for the",
  620. "dual rotation.  Subsequent continuous rotations of the object will have the",
  621. "dual superimposed on it.  'Shift-d' will erase the dual rotation setting.",
  622. "",
  623. "Pressing 'x' will reset the object to its initial position in 4D, and cancel",
  624. "all rotations.",
  625. "",
  626. "Press 'c' to toggle between two color sets (the 'white' set is intended for",
  627. "printing).  'Shift-c' brings up a color requester.",
  628. "",
  629. "The Tesseract program's source code is a combination of 'C' and assembly",
  630. "using Manx Aztec 'C' v3.6a.  The source contains examples of double-",
  631. "buffering, fixed- and floating-point math, and in-line assembly code.  I also",
  632. "used some of the code from Jonathan Potter's color requester.  Send $5.00 to",
  633. "obtain a disk containing source code and updated program.",
  634. "",
  635. "        Comments,                        Jerry D. Hedden",
  636. "        Questions,          \\\\           28 Windemere Dr.",
  637. "        Bug reports,         >>>>>>      Sicklerville, NJ  08081",
  638. "        Source requests,    //           Phone:  (609)629-3975",
  639. "        etc.                             Email:  Hedden@ESDSDF.DNet.GE.com",
  640. NULL
  641. };
  642.  
  643.  
  644. info()
  645. {
  646.   register long line;
  647.   register struct Window *info_window;
  648.   register struct IntuiMessage *msg;
  649.   register ULONG class;
  650.   register short all_done;
  651.  
  652.   MyWindow.IDCMPFlags = CLOSEWINDOW;
  653.   MyWindow.Flags = SIMPLE_REFRESH|NOCAREREFRESH|ACTIVATE|WINDOWCLOSE;
  654.   MyWindow.Title = (UBYTE *)InfoTitle;
  655.  
  656.   if (!(info_window = OpenWindow(&MyWindow)))   return;
  657.  
  658.   for (line = 0; Text.IText = (UBYTE *)InfoText[line]; line++)
  659.     PrintIText(info_window->RPort,&Text,TEXT_MARGIN,TEXT_START+(line<<3));
  660.  
  661.   for (all_done=0; !all_done; ) {
  662.     _WaitPort(info_window->UserPort);
  663.     while (msg = _GetMsg(info_window->UserPort)) {
  664.       class = msg->Class;
  665.       _ReplyMsg(msg);
  666.       if (class == CLOSEWINDOW)  all_done = 1;
  667.     }
  668.   }
  669.   CloseWindow(info_window);
  670. }
  671.  
  672.  
  673. /*** common requester stuff ***/
  674.  
  675. #define RESET    41
  676. #define CANCEL    42
  677. #define OKAY    43
  678.  
  679. short border_xy[] = {0,0, 115,0, 115,10, 0,10, 0,0};
  680. struct Border MyBorder = {-1,-1,1,0,JAM1,5,border_xy,NULL};
  681.  
  682. struct IntuiText
  683.   OkayText   = {1,0,JAM1, 41,1,NULL,(UBYTE *)"OKAY",  NULL},
  684.   ResetText  = {1,0,JAM1, 37,1,NULL,(UBYTE *)"RESET", NULL},
  685.   CancelText = {1,0,JAM1, 33,1,NULL,(UBYTE *)"CANCEL",NULL};
  686.  
  687. struct Image PropImage1, PropImage2, PropImage3;
  688.  
  689. struct Window *ReqWindow;
  690.  
  691.  
  692. /*** Color Requester ***/
  693.  
  694. #define RED    31
  695. #define GREEN    32
  696. #define BLUE    33
  697.  
  698. struct IntuiText
  699.   RedText    = {1,0,JAM1,-14,2,NULL,(UBYTE *)"R",NULL},
  700.   GreenText  = {1,0,JAM1,-14,2,NULL,(UBYTE *)"G",NULL},
  701.   BlueText   = {1,0,JAM1,-14,2,NULL,(UBYTE *)"B",NULL},
  702.   ValuesText = {0,1,JAM2,  0,0,NULL,(UBYTE *)"RGB",NULL};
  703.  
  704. struct PropInfo
  705.   RedProp   = {AUTOKNOB|FREEHORIZ,0,0,0x1000},
  706.   GreenProp = {AUTOKNOB|FREEHORIZ,0,0,0x1000},
  707.   BlueProp  = {AUTOKNOB|FREEHORIZ,0,0,0x1000};
  708.  
  709. struct Image CurColorImage = {0,0,235,8,1,NULL,0,1,NULL};
  710.  
  711. struct Gadget
  712.   RedCGadg = {NULL,24,54,100,11,
  713.     GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  714.     (APTR)&PropImage1,NULL,&RedText,NULL,(APTR)&RedProp,RED,NULL},
  715.   GreenCGadg = {&RedCGadg,24,66,100,11,
  716.     GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  717.     (APTR)&PropImage2,NULL,&GreenText,NULL,(APTR)&GreenProp,GREEN,NULL},
  718.   BlueCGadg = {&GreenCGadg,24,78,100,11,
  719.     GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  720.     (APTR)&PropImage3,NULL,&BlueText,NULL,(APTR)&BlueProp,BLUE,NULL},
  721.   OkayCGadg = {&BlueCGadg,130,79,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  722.     (APTR)&MyBorder,NULL,&OkayText,NULL,NULL,OKAY,NULL},
  723.   ResetCGadg = {&OkayCGadg,130,67,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  724.     (APTR)&MyBorder,NULL,&ResetText,NULL,NULL,RESET,NULL},
  725.   CancelCGadg = {&ResetCGadg,130,55,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  726.     (APTR)&MyBorder,NULL,&CancelText,NULL,NULL,CANCEL,NULL};
  727.  
  728. struct NewWindow ColorNewWindow={
  729.   40,23,255,93,0,1,GADGETUP|GADGETDOWN|MOUSEBUTTONS|RAWKEY,
  730.   ACTIVATE|SIMPLE_REFRESH|NOCAREREFRESH|RMBTRAP,
  731.   &CancelCGadg,NULL,(UBYTE *)" Tesseract's Color Requester",
  732.   NULL,NULL,0,0,0,0,CUSTOMSCREEN};
  733.  
  734. long CurColor;
  735.  
  736.  
  737. ColorRequester(ColorSet)
  738. short ColorSet;
  739. {
  740.   register long i;
  741.   register ULONG Class;
  742.   register USHORT Code, GadgetID;
  743.   register struct IntuiMessage *msg;
  744.  
  745.   ColorNewWindow.Screen = screen;
  746.   if (!(ReqWindow = OpenWindow(&ColorNewWindow)))  return;
  747.  
  748.   for (i=0; i < (1<<PLANES); i++)
  749.     ColorTables[2][i] = ColorTables[ColorSet][i];
  750.  
  751.   DrawPalette(PLANES);
  752.   CurColorImage.PlaneOnOff = CurColor = 1;
  753.   ValuesText.FrontPen = CurColor^((1<<PLANES)-1);
  754.   ValuesText.BackPen = 1;
  755.   DrawImage(ReqWindow->RPort,&CurColorImage,10L,45L);
  756.   SetRGBProps();
  757.  
  758.   FOREVER {
  759.     _WaitPort(ReqWindow->UserPort);
  760.     while (msg = _GetMsg(ReqWindow->UserPort)) {
  761.       Class = msg->Class;  Code = msg->Code;
  762.       if (Class == GADGETUP  ||  Class == GADGETDOWN)
  763.     GadgetID = ((struct Gadget *)msg->IAddress)->GadgetID;
  764.       _ReplyMsg(msg);
  765.       switch (Class) {
  766.     case MOUSEBUTTONS: {
  767.       long x,y;
  768.       long NewColor, ReadPixel();
  769.       if (Code != SELECTDOWN)  break;
  770.       x=ReqWindow->MouseX;    y=ReqWindow->MouseY;
  771.       if (x<12 || x>243 || y<15 || y>40)  break;
  772.       if (CurColor == (NewColor = ReadPixel(ReqWindow->RPort,x,y)))  break;
  773.       CurColorImage.PlaneOnOff = CurColor = NewColor;
  774.       DrawImage(ReqWindow->RPort,&CurColorImage,10L,45L);
  775.       SetRGBProps();
  776.       break;
  777.       }
  778.     case GADGETDOWN:
  779.       if (GadgetID >= RED  &&  GadgetID <= BLUE) {
  780.         do {
  781.           ReadRGBProps();
  782.         } while (!(msg = _GetMsg(ReqWindow->UserPort)));
  783.         _ReplyMsg(msg);
  784.         ReadRGBProps();
  785.       }
  786.       break;
  787.     case RAWKEY:
  788.       if (Code != ESCAPE)  break;
  789.       GadgetID = RESET;
  790.     case GADGETUP:
  791.       switch (GadgetID) {
  792.         case RESET:
  793.           for (i=0; i < (1<<PLANES); i++)
  794.         ColorTables[2][i] = ColorTables[ColorSet][i];
  795.           LoadRGB4(vp, &ColorTables[2][0], 1L<<PLANES);
  796.           SetRGBProps();
  797.           break;
  798.         case OKAY:
  799.           for (i=0; i < (1<<PLANES); i++)
  800.         ColorTables[ColorSet][i] = ColorTables[2][i];
  801.         case CANCEL:
  802.           LoadRGB4(vp, &ColorTables[ColorSet][0], 1L<<PLANES);
  803.           while (msg = _GetMsg(ReqWindow->UserPort))  _ReplyMsg(msg);
  804.           CloseWindow(ReqWindow);
  805.           return;
  806.       }
  807.       }
  808.     }
  809.   }
  810. }
  811.  
  812.  
  813. SetRGBProps()
  814. {
  815.   register UWORD cval = ColorTables[2][CurColor];
  816.   NewModifyProp(&RedCGadg,  ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
  817.             (long)(((cval>>8)&0xf)*0x1111),0L,0x1000L,0L,1L);
  818.   NewModifyProp(&GreenCGadg,ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
  819.             (long)(((cval>>4)&0xf)*0x1111),0L,0x1000L,0L,1L);
  820.   NewModifyProp(&BlueCGadg, ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
  821.             (long)((cval&0xf)*0x1111),0L,0x1000L,0L,1L);
  822.   ShowRGBValues();
  823. }
  824.  
  825.  
  826. ReadRGBProps()
  827. {
  828.   register long re,gr,bl;
  829.  
  830.   re = RedProp.  HorizPot >> 12;
  831.   gr = GreenProp.HorizPot >> 12;
  832.   bl = BlueProp. HorizPot >> 12;
  833.   ColorTables[2][CurColor] = (re<<8)|(gr<<4)|bl;
  834.   SetRGB4(vp,CurColor,re,gr,bl);
  835.   ShowRGBValues();
  836. }
  837.  
  838.  
  839. char *hex = "0123456789ABCDEF";
  840.  
  841. ShowRGBValues()
  842. {
  843.   register UWORD cval = ColorTables[2][CurColor];
  844.   ValuesText.IText[0] = hex[(cval>>8)&0xf];
  845.   ValuesText.IText[1] = hex[(cval>>4)&0xf];
  846.   ValuesText.IText[2] = hex[ cval    &0xf];
  847.   ValuesText.FrontPen = CurColor^((1<<PLANES)-1);
  848.   ValuesText.BackPen  = CurColor;
  849.   PrintIText(ReqWindow->RPort,&ValuesText,115L,45L);
  850. }
  851.  
  852.  
  853. DrawPalette(depth)
  854. int depth;
  855. {
  856.   long w,h,ox,x,y,i;
  857.  
  858. #if PLANES>3
  859.   if (depth==4)
  860.     { w=29; h=12; ox=13; }
  861.   else if (depth==5)
  862.     { w=14; h=12; ox=17; }
  863.   else
  864. #endif
  865.     { w=235/(1<<depth); h=25; ox=12; }
  866.   i=0; x=ox; y=15;
  867.   for (i=0; i<(1<<depth); i++) {
  868.     SetAPen(ReqWindow->RPort,i);
  869.     RectFill(ReqWindow->RPort,x,y,x+w,y+h);
  870. #if PLANES>3
  871.     if (depth>3 && i==(1<<(depth-1))-1) {
  872.       x=ox; y+=h;
  873.     } else
  874. #endif
  875.       x+=w;
  876.   }
  877. }
  878.  
  879.  
  880. #asm
  881. ; Stubs for accessing the math libraries
  882.  
  883.     public    _MathBase
  884.  
  885. _LVOSPMul    equ    -78
  886. _LVOSPSub    equ    -72
  887. _LVOSPAdd    equ    -66
  888. _LVOSPTst    equ    -48
  889. _LVOSPFlt    equ    -36
  890. _LVOSPFix    equ    -30
  891.  
  892.     public    _SPFix
  893. _SPFix
  894.     move.l    4(sp),d0
  895.     move.l    _MathBase,a6
  896.     jmp    _LVOSPFix(a6)
  897.  
  898.     public    _SPFlt
  899. _SPFlt
  900.     move.l    4(sp),d0
  901.     move.l    _MathBase,a6
  902.     jmp    _LVOSPFlt(a6)
  903.  
  904.     public    _SPAdd
  905. _SPAdd
  906.     move.l    4(sp),d1
  907.     move.l    12(sp),d0
  908.     move.l    _MathBase,a6
  909.     jmp    _LVOSPAdd(a6)
  910.  
  911.     public    _SPSub
  912. _SPSub
  913.     move.l    4(sp),d1
  914.     move.l    12(sp),d0
  915.     move.l    _MathBase,a6
  916.     jmp    _LVOSPSub(a6)
  917.  
  918.     public    _SPMul
  919. _SPMul
  920.     move.l    4(sp),d1
  921.     move.l    12(sp),d0
  922.     move.l    _MathBase,a6
  923.     jmp    _LVOSPMul(a6)
  924.  
  925.     public    _SPTst
  926. _SPTst
  927.     move.l    4(sp),d1
  928.     move.l    _MathBase,a6
  929.     jmp    _LVOSPTst(a6)
  930.  
  931.  
  932.     public    _MathTransBase
  933. _LVOSPSincos    equ    -54
  934. _LVOSPSqrt    equ    -96
  935.  
  936.     public    _SPSincos
  937. _SPSincos
  938.     move.l    4(sp),d1
  939.     move.l    8(sp),d0
  940.     move.l    _MathTransBase,a6
  941.     jmp    _LVOSPSincos(a6)
  942.  
  943.     public    _SPSqrt
  944. _SPSqrt
  945.     move.l    4(sp),d0
  946.     move.l    _MathTransBase,a6
  947.     jmp    _LVOSPSqrt(a6)
  948. #endasm
  949.