home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 100.lha / Planete / planet.c < prev    next >
C/C++ Source or Header  |  1986-11-20  |  15KB  |  598 lines

  1. #include "planet.h"
  2.  
  3. main(argc,argv)
  4. int argc;
  5. char *argv[];
  6. {
  7.    struct IntuiMessage *mess;
  8.    unsigned int mask,open_things();
  9.    int i,j,rad,ang;
  10.    long x,y,lx,ly,lz,vx,vy,vz,px,py,pz,v,pz2,r2;
  11.    float size,source,calp,lon,lat,light[3][3],trans[3][3];
  12.    char *c;
  13.  
  14. /* default values */
  15.  
  16.    mapfile = (UBYTE *)"planet.map\0         ";
  17.    rad = 180;
  18.    dmax = 6;
  19.    size = 1.0;
  20.  
  21. /* setup identity matrices for light source and planet rotation */
  22.  
  23.    for(i = 0; i < 3; i++)
  24.    {
  25.       for(j = 0; j < 3; j++)
  26.       {
  27.          if(i == j) light[i][j] = trans[i][j] = 1;
  28.          else light[i][j] = trans[i][j] = 0;
  29.       }
  30.    }
  31.  
  32. /* read command line argument values */
  33.  
  34.    for(i = 1; i < argc; i++)
  35.    {
  36.       c = argv[i];
  37.       if(c[0] == '?') help();
  38.       else if(c[0] == '-')
  39.       {
  40.          switch(c[1])
  41.          {
  42.             case 'r' : if(argc > ++i) sscanf(argv[i],"%d",&rad);
  43.                        break;
  44.             case 'h' : if(argc > ++i) sscanf(argv[i],"%d",&dmax);
  45.                        break;
  46.             case 's' : if(argc > ++i) sscanf(argv[i],"%f",&size);
  47.                        break;
  48.             case 'l' : if(argc > ++i) sscanf(argv[i],"%d",&ang);
  49.                        rotate(c[2],ang,light);
  50.                        break;
  51.             case 'p' : if(argc > ++i) sscanf(argv[i],"%d",&ang);
  52.                        rotate(c[2],-ang,trans);
  53.                        break;
  54.             case 'f' : CMFF = TRUE;
  55.                        break;
  56.             default  : printf("Error in arguments\n");
  57.                        help();
  58.                        break;
  59.          }
  60.       }
  61.       else sscanf(argv[i],"%s",mapfile);
  62.    }
  63.  
  64. /* compute light source vector */
  65.  
  66.    lx = rad*light[0][2];
  67.    ly = rad*light[1][2];
  68.    lz = rad*light[2][2];
  69.    r2 = (long)(rad*rad);
  70.  
  71. /* compute light source size effect */
  72.  
  73.    source = 2*atan((double)(size - 1.0))/PI;
  74.  
  75.    mask = open_things();
  76.  
  77. /* loop on destination display coordinates */
  78.  
  79.    for (y = 0L; y < 400L; ++y)
  80.    {
  81.       py = 200L - y;
  82.       ro = go = bo = 0;
  83.  
  84.       for (x = 0L; x < 320L; ++x)
  85.       {
  86.          if(mess = (struct IntuiMessage *)GetMsg(w->UserPort))
  87.             CheckMess(mess,mask);
  88.          px = 25L*(x - 160L)/14L;
  89.  
  90.          /* calculate for coordinates on planet surface only */
  91.  
  92.          if((pz2 = r2 - (px*px + py*py)) > 0L)
  93.          {
  94.             pz = sqrt((double)pz2);
  95.  
  96.             /* compute cosine of angle between normal and light source */
  97.  
  98.             vx = px*trans[0][0] + py*trans[0][1] + pz*trans[0][2];
  99.             vy = px*trans[1][0] + py*trans[1][1] + pz*trans[1][2];
  100.             vz = px*trans[2][0] + py*trans[2][1] + pz*trans[2][2];
  101.             calp = (vx*lx + vy*ly + vz*lz)/(float)r2;
  102.             calp = (calp + source)/(1 + source);
  103.  
  104.             /* dont bother with black part of planet */
  105.  
  106.             if(calp > 0.0)
  107.             {
  108.                if(calp > 1.0) calp = 1.0;
  109.  
  110.                /* compute longitude and latitude */
  111.  
  112.                if((v = sqrt((double)(vy*vy + vz*vz))) == 0) v = 1;
  113.                lon = atan((double)vx/v);
  114.                if((v = sqrt((double)(vx*vx + vz*vz))) == 0) v = 1;
  115.                lat = atan((double)vy/v);
  116.  
  117.                /* get color from planet map */
  118.  
  119.                map(lon,lat);
  120.                PutPixel(x,y,calp);
  121.             }
  122.          }
  123.       }
  124.    }
  125.  
  126.    close_things((unsigned int)ILBM);
  127.    mask ^= ILBM;
  128.  
  129.    for(;;)
  130.    {
  131.       Wait(1L << w->UserPort->mp_SigBit);
  132.       if(mess = (struct IntuiMessage *)GetMsg(w->UserPort))
  133.          CheckMess(mess,mask);
  134.    }
  135. } /* end main */
  136.  
  137. /* compute transformation and concatenate with previous transformation(s) */
  138.  
  139. rotate(axis,ang,m)
  140. int axis,ang;
  141. float (*m)[3];
  142. {
  143.    int i,j,k;
  144.    float n[3][3],p[3][3];
  145.  
  146.    /* setup tranformation matrix based on selected axis */
  147.  
  148.    switch(axis)
  149.    {
  150.       case 'x': i = 0; j = 1; k = 2; break;
  151.       case 'y': i = 1; j = 2; k = 0; break;
  152.       case 'z': i = 2; j = 0; k = 1; break;
  153.       default : i = 0; j = 1; k = 2; break;
  154.    }
  155.  
  156.    n[i][i] = 1.0;
  157.    n[j][j] = n[k][k] = cos((double)ang*PI/180);
  158.    n[i][j] = n[i][k] = n[j][i] = n[k][i] = 0.0;
  159.    n[k][j] = sin((double)ang*PI/180);
  160.    n[j][k] = -n[k][j];
  161.  
  162.    /* concatenate with previously computed transformation matrix */
  163.  
  164.    for(i = 0; i < 3; i++)
  165.    {
  166.       for(j = 0; j < 3; j++)
  167.       {
  168.          p[i][j] = 0.0;
  169.          for(k = 0; k < 3; k++) p[i][j] = p[i][j] + n[i][k]*m[k][j];
  170.       }
  171.    }
  172.  
  173.    for(j = 0; j < 3; j++)
  174.    {
  175.       for(i = 0; i < 3; i++) m[i][j] = p[i][j];
  176.    }
  177. } /* end rotate */
  178.  
  179. /* self explanitory */
  180.  
  181. help()
  182. {
  183.    printf
  184.    ("usage: planet [1] -r [2] -h [3] -s [4] -l[x,y,z 5] -p[x,y,z 6] -f [7]\n");
  185.    printf
  186.    ("    1: map file name (IFF);                     any ILBM [planet.map]\n");
  187.    printf
  188.    ("    2: radius of planet (pixels);               10   -> 180  [180]\n");
  189.    printf
  190.    ("    3: ham tweek factor (color gradients);      0    -> 45   [6]\n");
  191.    printf
  192.    ("    4: radius of light source (planet radii);   0.0  -> 10.0 [1.0]\n");
  193.    printf
  194.    ("    5: light source angle about axis (degrees); 0    -> 360  [x 0]\n");
  195.    printf
  196.    ("    6: planet rotation about axis (degrees);    0    -> 360  [x 0]\n");
  197.    printf
  198.    ("    7: color map from file;                     no argument\n");
  199.    exit(0);
  200. } /* end help */
  201.  
  202. /* get color from map at specified longitude and latitude */
  203.  
  204. map(lon,lat)
  205. float lon,lat;
  206. {
  207.    int x,y,i,id;
  208.  
  209.    x = (lon/PI + .5)*(Width-1);
  210.    y = (.5 - lat/PI)*(Height-1);
  211.  
  212.    /* if map is HAM mode then full scan line must be processed */
  213.  
  214.    if(ViewModes & HAM) {
  215.       rc = gc = bc = 0;
  216.       for(i = 0; i <= x; i++) {
  217.          id = ReadPixel(&maprp,(long)i,(long)y);
  218.          if((id & 48) == 32) rc = (id & 15);
  219.          else if((id & 48) == 48) gc = (id & 15);
  220.          else if((id & 48) == 16) bc = (id & 15);
  221.          else {
  222.             rc = rm[id];
  223.             gc = gm[id];
  224.             bc = bm[id];
  225.          }
  226.       }
  227.    }
  228.  
  229.    /* else just read color value from map */
  230.  
  231.    else {
  232.       id = ReadPixel(&maprp,(long)x,(long)y);
  233.       rc = rm[id];
  234.       gc = gm[id];
  235.       bc = bm[id];
  236.    }
  237. } /* end map */
  238.  
  239. /* compute planet color value with shade applied */
  240.  
  241. PutPixel(x,y,ca)
  242. long x,y;
  243. float ca;
  244. {
  245.    int r,g,b,dr,dg,db,val,d,diff,n;
  246.  
  247.    /* multiply each color component with shade value */
  248.  
  249.    r = ca*rc;
  250.    g = ca*gc;
  251.    b = ca*bc;
  252.  
  253.    /* compute closest HAM color to desired color */
  254.  
  255.    dr = ABS(r - ro);
  256.    dg = ABS(g - go);
  257.    db = ABS(b - bo);
  258.  
  259.    if(dr > dg) {
  260.       if(dr > db) { ro = r; dr = 0; val = r + 32; }
  261.       else        { bo = b; db = 0; val = b + 16; }
  262.    }
  263.    else {
  264.       if(dg > db) { go = g; dg = 0; val = g + 48; }
  265.       else        { bo = b; db = 0; val = b + 16; }
  266.    }
  267.  
  268.    diff = dr + dg + db;
  269.  
  270.    /* check to see if any existing color comes closer */
  271.  
  272.    for(n = nc; n >= 0; n--)
  273.    {
  274.       dr = ABS(r - rn[n]);
  275.       dg = ABS(g - gn[n]);
  276.       db = ABS(b - bn[n]);
  277.       d = dr + dg + db;
  278.  
  279.       if(d <= diff) {
  280.          diff = d;
  281.          val = n;
  282.          ro = rn[n];
  283.          go = gn[n];
  284.          bo = bn[n];
  285.       }
  286.    }
  287.  
  288.    /* if the difference between obtainable color and desired color exceeds
  289.       maximum difference (HAM tweek factor) then place desired color into
  290.       palatte (if there is room) and update color bar */
  291.  
  292.    if((diff > dmax) && (nc < NCOL)) {
  293.       val = ++nc;
  294.       ro = rn[nc] = r;
  295.       go = gn[nc] = g;
  296.       bo = bn[nc] = b;
  297.       SetRGB4(vp,(long)nc,(long)r,(long)g,(long)b);
  298.       if(showtitle) DrawImage(trp,&square[15],0L,0L);
  299.    }
  300.  
  301.    /* set color on displayed planet */
  302.  
  303.    SetAPen(rp,(long)val);
  304.    WritePixel(rp,x,y);
  305.  
  306. } /* end PutPixel */
  307.  
  308. /* check to see what the user wants */
  309.  
  310. CheckMess(message,mask)
  311. struct IntuiMessage *message;
  312. unsigned int mask;
  313. {
  314.    ULONG class;
  315.    unsigned int code,menunum,itemnum;
  316.  
  317.    class = message->Class;
  318.    code = message->Code;
  319.    ReplyMsg(message);
  320.    if(class == MENUPICK)
  321.    {
  322.       menunum = MENUNUM(code);
  323.       itemnum = ITEMNUM(code);
  324.       switch(menunum)
  325.       {
  326.          case 0:
  327.          switch(itemnum)
  328.          {
  329.             case 0:
  330.             TitleShow();
  331.             break;
  332.  
  333.             case 1:
  334.             close_things(mask);
  335.         exit(0);
  336.          }
  337.       }
  338.       if(showtitle) DrawImage(trp,&square[15],0L,0L);      
  339.    }
  340. } /* end CheckMess */
  341.  
  342. /* open everything */
  343.  
  344. unsigned int open_things()
  345. {
  346.    unsigned int mask;
  347.    int i;
  348.  
  349.    struct Library *OpenLibrary();
  350.    struct Screen *OpenScreen();
  351.    struct Window *OpenWindow();
  352.    struct ViewPort *ViewPortAddress();
  353.  
  354.    mask = 0;
  355.  
  356.    if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L)))
  357.    {
  358.       printf("no graphics library!!!\n");
  359.       exit(1);
  360.    }
  361.    mask |= GRAPHICS;
  362.  
  363.    if(!(IntuitionBase = (struct IntuitionBase *)
  364.         OpenLibrary("intuition.library",0L)))
  365.    {
  366.       printf("no intuition library!!!\n");
  367.       close_things(mask);
  368.       exit(2);
  369.    }
  370.    mask |= INTUITION;
  371.  
  372.    ns.DefaultTitle = mapfile;
  373.  
  374.    if (!(s = OpenScreen(&ns)))
  375.    {
  376.       printf("could not open the screen\n");
  377.       close_things(mask);
  378.       exit(3);
  379.    }
  380.    mask |= SCREEN;
  381.  
  382.    nw.Screen = s;
  383.  
  384.    if (!(w = OpenWindow(&nw)))
  385.    {
  386.       printf("could not open the window\n");
  387.       close_things(mask);
  388.       exit(4);
  389.    }
  390.    mask |= WINDOW;
  391.  
  392.    rp = w->RPort;
  393.    vp = ViewPortAddress(w);
  394.  
  395.    SetMenuStrip(w,&ScrnMenu);
  396.    showtitle = TRUE;
  397.    TitleShow();
  398.  
  399.    if (!ReadILBM(mapfile))
  400.    {
  401.       printf("could not get ILBM\n");
  402.       close_things(mask);
  403.       exit(5);
  404.    }
  405.    mask |= ILBM;
  406.  
  407.    /* setup color bar */
  408.  
  409.    for(i=0;i<16;i++) {
  410.       SetRGB4(vp,(long)i,(long)rn[i],(long)gn[i],(long)bn[i]);
  411.       square[i].LeftEdge = 158 + 8*i;
  412.       square[i].TopEdge = 0;
  413.       square[i].Width = 8;
  414.       square[i].Height = 10;
  415.       square[i].Depth = 0;
  416.       square[i].ImageData = NULL;
  417.       square[i].PlanePick = 0;
  418.       square[i].PlaneOnOff = i;
  419.       if(i != 0) square[i].NextImage = &square[i-1];
  420.    }
  421.    square[0].NextImage = NULL;
  422.    trp = s->BarLayer->rp;
  423.  
  424.    return(mask);
  425. } /* end open_things */
  426.  
  427. /* close things indicated by mask */
  428.  
  429. close_things(mask)
  430. unsigned int mask;
  431. {
  432.    int i;
  433.  
  434.    if(mask & ILBM)
  435.    {
  436.       FreeMem(bufstart,(long)header.ckSize);
  437.       for(i=0;i<Depth;i++)
  438.          FreeMem(bmap.Planes[i],PlaneSize);
  439.    }
  440.    if(mask & WINDOW)
  441.    {
  442.       ClearMenuStrip(w);
  443.       CloseWindow(w);
  444.    }
  445.    if(mask & SCREEN)    CloseScreen(s);
  446.    if(mask & GRAPHICS)  CloseLibrary(GfxBase);
  447.    if(mask & INTUITION) CloseLibrary(IntuitionBase);
  448. } /* end close_things */
  449.  
  450. /* toggle title bar */
  451.  
  452. TitleShow()
  453. {
  454.    ClearMenuStrip(w);
  455.    if(showtitle)
  456.    {
  457.       showtitle = FALSE;
  458.       ScrnText1.IText = (UBYTE *)"Show Title Bar";
  459.       ShowTitle(s,FALSE);
  460.    }
  461.    else
  462.    {
  463.       showtitle = TRUE;
  464.       ScrnText1.IText = (UBYTE *)"Hide Title Bar";
  465.       ShowTitle(s,TRUE);
  466.       DrawImage(trp,&square[15],0L,0L);
  467.    }
  468.    SetMenuStrip(w,&ScrnMenu);
  469. } /* end TitleShow */
  470.  
  471. /**************************************************************************
  472. *                                                                         *
  473. *    Routine name(s) : ReadILBM()                                         *
  474. *    Author          : D. John Hodgson (modified by Russell Leighton)     *
  475. *    Environment     : Aztec "C", default                                 *
  476. *                                                                         *
  477. *    ReadILBM attempts to read an IFF file. If successful then contents   *
  478. *    are stored in bitmap, bmap and a rastport, maprp is initialized. The *
  479. *    colormap is stored (the RGB components are kept separate) in the     *
  480. *    array, mapcolors.                                                    *
  481. *                                                                         *
  482. *    LIMITATIONS : no masking, CATS/LISTS/PROPS. CAMG chunks supported.   *
  483. **************************************************************************/
  484.  
  485. int ReadILBM(fspec)
  486. char *fspec; /* AmigaDOS filename */
  487. {
  488.   struct FileHandle *fp,*Open();
  489.   UBYTE *sourcebuf,*destbuf,*AllocMem();
  490.   UBYTE colormap[MAXCOLORS][3];
  491.   short colorcount,plane,linelen,rowbytes,i,r,g,b;
  492.   long id;
  493.   char n;
  494.  
  495.   if ((fp=Open(fspec,MODE_OLDFILE))==NULL) return(0);
  496.  
  497.   SafeRead(fp,&header,(long)sizeof(header));
  498.   if (header.ckID!=ID_FORM) { Close(fp); return(0); }
  499.  
  500.   SafeRead(fp,&id,(long)sizeof(id));
  501.   if (id!=ID_ILBM) { Close(fp); return(0); }
  502.  
  503.   for (;;) {
  504.     SafeRead(fp,&header,(long)sizeof(header));
  505.  
  506.     if (header.ckID==ID_BODY) break;
  507.  
  508.     switch(header.ckID) {
  509.       case ID_BMHD: SafeRead(fp,&bmhd,(long)sizeof(bmhd));
  510.                     break;
  511.  
  512.       case ID_CMAP: SafeRead(fp,&colormap[0][0],(long)header.ckSize);
  513.                     colorcount=header.ckSize/3;
  514.                     break;
  515.  
  516.       case ID_CAMG: SafeRead(fp,&ViewModes,(long)header.ckSize);
  517.                     break;
  518.  
  519.       default:      Seek(fp,ROUNDODDUP(header.ckSize),OFFSET_CURRENT);
  520.     }
  521.   }
  522.  
  523.   /* Read planes into RAM for ease if decompression */
  524.      
  525.   sourcebuf=bufstart=AllocMem((long)header.ckSize,MEMF_PUBLIC | MEMF_CHIP);
  526.   if (sourcebuf==NULL) return(0);
  527.  
  528.   SafeRead(fp,sourcebuf,(long)header.ckSize); Close(fp);
  529.  
  530.   Width=bmhd.w;
  531.   Height=bmhd.h;
  532.   Depth=bmhd.nPlanes;
  533.  
  534.   /* make some forced assumptions if CAMG chunk unavailable */
  535.  
  536.   if (ViewModes == 0L) {
  537.     if (Width > MAXWIDTH) ViewModes |= HIRES;
  538.     if (Height > MAXHEIGHT) ViewModes |= LACE;
  539.   }
  540.  
  541.   linelen=Width/8;
  542.  
  543.   bmap.BytesPerRow = linelen;
  544.   bmap.Rows = Height;
  545.   bmap.Depth = (UBYTE)Depth;
  546.  
  547.   PlaneSize = (long)(linelen*Height);
  548.   for(i=0;i<Depth;i++) { /* allocate space for bitmap */
  549.     bmap.Planes[i] = AllocMem(PlaneSize,MEMF_PUBLIC | MEMF_CHIP);
  550.     if(bmap.Planes[i] == NULL) return(0);
  551.   }
  552.  
  553.   maprp.BitMap=&bmap;
  554.  
  555.   while (colorcount--) {
  556.     rm[colorcount] = colormap[colorcount][0] >> 4L;
  557.     gm[colorcount] = colormap[colorcount][1] >> 4L;
  558.     bm[colorcount] = colormap[colorcount][2] >> 4L;
  559.     if(CMFF && (colorcount < 16)) {
  560.        rn[colorcount] = rm[colorcount];
  561.        gn[colorcount] = gm[colorcount];
  562.        bn[colorcount] = bm[colorcount];
  563.     }
  564.   }
  565.  
  566.   if(CMFF) nc = NCOL;
  567.  
  568.   for (i=0;i<Height;i++) /* process n lines/screen */
  569.     for (plane=0;plane<Depth;plane++) { /* process n planes/line */
  570.       destbuf=(UBYTE *)(bmap.Planes[plane])+linelen*i;
  571.  
  572.       if (bmhd.compression==cmpByteRun1) { /* compressed screen? */
  573.         rowbytes=linelen;
  574.  
  575.         while (rowbytes) { /* unpack until 1 scan-line complete */
  576.           n=*sourcebuf++; /* fetch block run marker */
  577.  
  578.           /* uncompressed block? copy n bytes verbatim */
  579.           if (n>=0) {
  580.             movmem(sourcebuf,destbuf,(unsigned int)++n); rowbytes-=n;
  581.             destbuf+=n; sourcebuf+=n;
  582.           }
  583.           else { /* compressed block? expand n duplicate bytes */
  584.             n=-n+1; rowbytes-=n;
  585.             setmem(destbuf,(unsigned int)n,(unsigned int)*sourcebuf++);
  586.             destbuf+=n;
  587.           }
  588.  
  589.         } /* finish unpacking line */
  590.       }
  591.       else { /* uncompressed? just copy */
  592.         movmem(sourcebuf,destbuf,(unsigned int)linelen);
  593.         sourcebuf+=linelen; destbuf+=linelen;
  594.       }
  595.     } /* finish interleaved planes, lines */
  596.   return(1);
  597. } /* end ReadILBM */
  598.