home *** CD-ROM | disk | FTP | other *** search
- #include "planet.h"
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- struct IntuiMessage *mess;
- unsigned int mask,open_things();
- int i,j,rad,ang;
- long x,y,lx,ly,lz,vx,vy,vz,px,py,pz,v,pz2,r2;
- float size,source,calp,lon,lat,light[3][3],trans[3][3];
- char *c;
-
- /* default values */
-
- mapfile = (UBYTE *)"planet.map\0 ";
- rad = 180;
- dmax = 6;
- size = 1.0;
-
- /* setup identity matrices for light source and planet rotation */
-
- for(i = 0; i < 3; i++)
- {
- for(j = 0; j < 3; j++)
- {
- if(i == j) light[i][j] = trans[i][j] = 1;
- else light[i][j] = trans[i][j] = 0;
- }
- }
-
- /* read command line argument values */
-
- for(i = 1; i < argc; i++)
- {
- c = argv[i];
- if(c[0] == '?') help();
- else if(c[0] == '-')
- {
- switch(c[1])
- {
- case 'r' : if(argc > ++i) sscanf(argv[i],"%d",&rad);
- break;
- case 'h' : if(argc > ++i) sscanf(argv[i],"%d",&dmax);
- break;
- case 's' : if(argc > ++i) sscanf(argv[i],"%f",&size);
- break;
- case 'l' : if(argc > ++i) sscanf(argv[i],"%d",&ang);
- rotate(c[2],ang,light);
- break;
- case 'p' : if(argc > ++i) sscanf(argv[i],"%d",&ang);
- rotate(c[2],-ang,trans);
- break;
- case 'f' : CMFF = TRUE;
- break;
- default : printf("Error in arguments\n");
- help();
- break;
- }
- }
- else sscanf(argv[i],"%s",mapfile);
- }
-
- /* compute light source vector */
-
- lx = rad*light[0][2];
- ly = rad*light[1][2];
- lz = rad*light[2][2];
- r2 = (long)(rad*rad);
-
- /* compute light source size effect */
-
- source = 2*atan((double)(size - 1.0))/PI;
-
- mask = open_things();
-
- /* loop on destination display coordinates */
-
- for (y = 0L; y < 400L; ++y)
- {
- py = 200L - y;
- ro = go = bo = 0;
-
- for (x = 0L; x < 320L; ++x)
- {
- if(mess = (struct IntuiMessage *)GetMsg(w->UserPort))
- CheckMess(mess,mask);
- px = 25L*(x - 160L)/14L;
-
- /* calculate for coordinates on planet surface only */
-
- if((pz2 = r2 - (px*px + py*py)) > 0L)
- {
- pz = sqrt((double)pz2);
-
- /* compute cosine of angle between normal and light source */
-
- vx = px*trans[0][0] + py*trans[0][1] + pz*trans[0][2];
- vy = px*trans[1][0] + py*trans[1][1] + pz*trans[1][2];
- vz = px*trans[2][0] + py*trans[2][1] + pz*trans[2][2];
- calp = (vx*lx + vy*ly + vz*lz)/(float)r2;
- calp = (calp + source)/(1 + source);
-
- /* dont bother with black part of planet */
-
- if(calp > 0.0)
- {
- if(calp > 1.0) calp = 1.0;
-
- /* compute longitude and latitude */
-
- if((v = sqrt((double)(vy*vy + vz*vz))) == 0) v = 1;
- lon = atan((double)vx/v);
- if((v = sqrt((double)(vx*vx + vz*vz))) == 0) v = 1;
- lat = atan((double)vy/v);
-
- /* get color from planet map */
-
- map(lon,lat);
- PutPixel(x,y,calp);
- }
- }
- }
- }
-
- close_things((unsigned int)ILBM);
- mask ^= ILBM;
-
- for(;;)
- {
- Wait(1L << w->UserPort->mp_SigBit);
- if(mess = (struct IntuiMessage *)GetMsg(w->UserPort))
- CheckMess(mess,mask);
- }
- } /* end main */
-
- /* compute transformation and concatenate with previous transformation(s) */
-
- rotate(axis,ang,m)
- int axis,ang;
- float (*m)[3];
- {
- int i,j,k;
- float n[3][3],p[3][3];
-
- /* setup tranformation matrix based on selected axis */
-
- switch(axis)
- {
- case 'x': i = 0; j = 1; k = 2; break;
- case 'y': i = 1; j = 2; k = 0; break;
- case 'z': i = 2; j = 0; k = 1; break;
- default : i = 0; j = 1; k = 2; break;
- }
-
- n[i][i] = 1.0;
- n[j][j] = n[k][k] = cos((double)ang*PI/180);
- n[i][j] = n[i][k] = n[j][i] = n[k][i] = 0.0;
- n[k][j] = sin((double)ang*PI/180);
- n[j][k] = -n[k][j];
-
- /* concatenate with previously computed transformation matrix */
-
- for(i = 0; i < 3; i++)
- {
- for(j = 0; j < 3; j++)
- {
- p[i][j] = 0.0;
- for(k = 0; k < 3; k++) p[i][j] = p[i][j] + n[i][k]*m[k][j];
- }
- }
-
- for(j = 0; j < 3; j++)
- {
- for(i = 0; i < 3; i++) m[i][j] = p[i][j];
- }
- } /* end rotate */
-
- /* self explanitory */
-
- help()
- {
- printf
- ("usage: planet [1] -r [2] -h [3] -s [4] -l[x,y,z 5] -p[x,y,z 6] -f [7]\n");
- printf
- (" 1: map file name (IFF); any ILBM [planet.map]\n");
- printf
- (" 2: radius of planet (pixels); 10 -> 180 [180]\n");
- printf
- (" 3: ham tweek factor (color gradients); 0 -> 45 [6]\n");
- printf
- (" 4: radius of light source (planet radii); 0.0 -> 10.0 [1.0]\n");
- printf
- (" 5: light source angle about axis (degrees); 0 -> 360 [x 0]\n");
- printf
- (" 6: planet rotation about axis (degrees); 0 -> 360 [x 0]\n");
- printf
- (" 7: color map from file; no argument\n");
- exit(0);
- } /* end help */
-
- /* get color from map at specified longitude and latitude */
-
- map(lon,lat)
- float lon,lat;
- {
- int x,y,i,id;
-
- x = (lon/PI + .5)*(Width-1);
- y = (.5 - lat/PI)*(Height-1);
-
- /* if map is HAM mode then full scan line must be processed */
-
- if(ViewModes & HAM) {
- rc = gc = bc = 0;
- for(i = 0; i <= x; i++) {
- id = ReadPixel(&maprp,(long)i,(long)y);
- if((id & 48) == 32) rc = (id & 15);
- else if((id & 48) == 48) gc = (id & 15);
- else if((id & 48) == 16) bc = (id & 15);
- else {
- rc = rm[id];
- gc = gm[id];
- bc = bm[id];
- }
- }
- }
-
- /* else just read color value from map */
-
- else {
- id = ReadPixel(&maprp,(long)x,(long)y);
- rc = rm[id];
- gc = gm[id];
- bc = bm[id];
- }
- } /* end map */
-
- /* compute planet color value with shade applied */
-
- PutPixel(x,y,ca)
- long x,y;
- float ca;
- {
- int r,g,b,dr,dg,db,val,d,diff,n;
-
- /* multiply each color component with shade value */
-
- r = ca*rc;
- g = ca*gc;
- b = ca*bc;
-
- /* compute closest HAM color to desired color */
-
- dr = ABS(r - ro);
- dg = ABS(g - go);
- db = ABS(b - bo);
-
- if(dr > dg) {
- if(dr > db) { ro = r; dr = 0; val = r + 32; }
- else { bo = b; db = 0; val = b + 16; }
- }
- else {
- if(dg > db) { go = g; dg = 0; val = g + 48; }
- else { bo = b; db = 0; val = b + 16; }
- }
-
- diff = dr + dg + db;
-
- /* check to see if any existing color comes closer */
-
- for(n = nc; n >= 0; n--)
- {
- dr = ABS(r - rn[n]);
- dg = ABS(g - gn[n]);
- db = ABS(b - bn[n]);
- d = dr + dg + db;
-
- if(d <= diff) {
- diff = d;
- val = n;
- ro = rn[n];
- go = gn[n];
- bo = bn[n];
- }
- }
-
- /* if the difference between obtainable color and desired color exceeds
- maximum difference (HAM tweek factor) then place desired color into
- palatte (if there is room) and update color bar */
-
- if((diff > dmax) && (nc < NCOL)) {
- val = ++nc;
- ro = rn[nc] = r;
- go = gn[nc] = g;
- bo = bn[nc] = b;
- SetRGB4(vp,(long)nc,(long)r,(long)g,(long)b);
- if(showtitle) DrawImage(trp,&square[15],0L,0L);
- }
-
- /* set color on displayed planet */
-
- SetAPen(rp,(long)val);
- WritePixel(rp,x,y);
-
- } /* end PutPixel */
-
- /* check to see what the user wants */
-
- CheckMess(message,mask)
- struct IntuiMessage *message;
- unsigned int mask;
- {
- ULONG class;
- unsigned int code,menunum,itemnum;
-
- class = message->Class;
- code = message->Code;
- ReplyMsg(message);
- if(class == MENUPICK)
- {
- menunum = MENUNUM(code);
- itemnum = ITEMNUM(code);
- switch(menunum)
- {
- case 0:
- switch(itemnum)
- {
- case 0:
- TitleShow();
- break;
-
- case 1:
- close_things(mask);
- exit(0);
- }
- }
- if(showtitle) DrawImage(trp,&square[15],0L,0L);
- }
- } /* end CheckMess */
-
- /* open everything */
-
- unsigned int open_things()
- {
- unsigned int mask;
- int i;
-
- struct Library *OpenLibrary();
- struct Screen *OpenScreen();
- struct Window *OpenWindow();
- struct ViewPort *ViewPortAddress();
-
- mask = 0;
-
- if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L)))
- {
- printf("no graphics library!!!\n");
- exit(1);
- }
- mask |= GRAPHICS;
-
- if(!(IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library",0L)))
- {
- printf("no intuition library!!!\n");
- close_things(mask);
- exit(2);
- }
- mask |= INTUITION;
-
- ns.DefaultTitle = mapfile;
-
- if (!(s = OpenScreen(&ns)))
- {
- printf("could not open the screen\n");
- close_things(mask);
- exit(3);
- }
- mask |= SCREEN;
-
- nw.Screen = s;
-
- if (!(w = OpenWindow(&nw)))
- {
- printf("could not open the window\n");
- close_things(mask);
- exit(4);
- }
- mask |= WINDOW;
-
- rp = w->RPort;
- vp = ViewPortAddress(w);
-
- SetMenuStrip(w,&ScrnMenu);
- showtitle = TRUE;
- TitleShow();
-
- if (!ReadILBM(mapfile))
- {
- printf("could not get ILBM\n");
- close_things(mask);
- exit(5);
- }
- mask |= ILBM;
-
- /* setup color bar */
-
- for(i=0;i<16;i++) {
- SetRGB4(vp,(long)i,(long)rn[i],(long)gn[i],(long)bn[i]);
- square[i].LeftEdge = 158 + 8*i;
- square[i].TopEdge = 0;
- square[i].Width = 8;
- square[i].Height = 10;
- square[i].Depth = 0;
- square[i].ImageData = NULL;
- square[i].PlanePick = 0;
- square[i].PlaneOnOff = i;
- if(i != 0) square[i].NextImage = &square[i-1];
- }
- square[0].NextImage = NULL;
- trp = s->BarLayer->rp;
-
- return(mask);
- } /* end open_things */
-
- /* close things indicated by mask */
-
- close_things(mask)
- unsigned int mask;
- {
- int i;
-
- if(mask & ILBM)
- {
- FreeMem(bufstart,(long)header.ckSize);
- for(i=0;i<Depth;i++)
- FreeMem(bmap.Planes[i],PlaneSize);
- }
- if(mask & WINDOW)
- {
- ClearMenuStrip(w);
- CloseWindow(w);
- }
- if(mask & SCREEN) CloseScreen(s);
- if(mask & GRAPHICS) CloseLibrary(GfxBase);
- if(mask & INTUITION) CloseLibrary(IntuitionBase);
- } /* end close_things */
-
- /* toggle title bar */
-
- TitleShow()
- {
- ClearMenuStrip(w);
- if(showtitle)
- {
- showtitle = FALSE;
- ScrnText1.IText = (UBYTE *)"Show Title Bar";
- ShowTitle(s,FALSE);
- }
- else
- {
- showtitle = TRUE;
- ScrnText1.IText = (UBYTE *)"Hide Title Bar";
- ShowTitle(s,TRUE);
- DrawImage(trp,&square[15],0L,0L);
- }
- SetMenuStrip(w,&ScrnMenu);
- } /* end TitleShow */
-
- /**************************************************************************
- * *
- * Routine name(s) : ReadILBM() *
- * Author : D. John Hodgson (modified by Russell Leighton) *
- * Environment : Aztec "C", default *
- * *
- * ReadILBM attempts to read an IFF file. If successful then contents *
- * are stored in bitmap, bmap and a rastport, maprp is initialized. The *
- * colormap is stored (the RGB components are kept separate) in the *
- * array, mapcolors. *
- * *
- * LIMITATIONS : no masking, CATS/LISTS/PROPS. CAMG chunks supported. *
- **************************************************************************/
-
- int ReadILBM(fspec)
- char *fspec; /* AmigaDOS filename */
- {
- struct FileHandle *fp,*Open();
- UBYTE *sourcebuf,*destbuf,*AllocMem();
- UBYTE colormap[MAXCOLORS][3];
- short colorcount,plane,linelen,rowbytes,i,r,g,b;
- long id;
- char n;
-
- if ((fp=Open(fspec,MODE_OLDFILE))==NULL) return(0);
-
- SafeRead(fp,&header,(long)sizeof(header));
- if (header.ckID!=ID_FORM) { Close(fp); return(0); }
-
- SafeRead(fp,&id,(long)sizeof(id));
- if (id!=ID_ILBM) { Close(fp); return(0); }
-
- for (;;) {
- SafeRead(fp,&header,(long)sizeof(header));
-
- if (header.ckID==ID_BODY) break;
-
- switch(header.ckID) {
- case ID_BMHD: SafeRead(fp,&bmhd,(long)sizeof(bmhd));
- break;
-
- case ID_CMAP: SafeRead(fp,&colormap[0][0],(long)header.ckSize);
- colorcount=header.ckSize/3;
- break;
-
- case ID_CAMG: SafeRead(fp,&ViewModes,(long)header.ckSize);
- break;
-
- default: Seek(fp,ROUNDODDUP(header.ckSize),OFFSET_CURRENT);
- }
- }
-
- /* Read planes into RAM for ease if decompression */
-
- sourcebuf=bufstart=AllocMem((long)header.ckSize,MEMF_PUBLIC | MEMF_CHIP);
- if (sourcebuf==NULL) return(0);
-
- SafeRead(fp,sourcebuf,(long)header.ckSize); Close(fp);
-
- Width=bmhd.w;
- Height=bmhd.h;
- Depth=bmhd.nPlanes;
-
- /* make some forced assumptions if CAMG chunk unavailable */
-
- if (ViewModes == 0L) {
- if (Width > MAXWIDTH) ViewModes |= HIRES;
- if (Height > MAXHEIGHT) ViewModes |= LACE;
- }
-
- linelen=Width/8;
-
- bmap.BytesPerRow = linelen;
- bmap.Rows = Height;
- bmap.Depth = (UBYTE)Depth;
-
- PlaneSize = (long)(linelen*Height);
- for(i=0;i<Depth;i++) { /* allocate space for bitmap */
- bmap.Planes[i] = AllocMem(PlaneSize,MEMF_PUBLIC | MEMF_CHIP);
- if(bmap.Planes[i] == NULL) return(0);
- }
-
- maprp.BitMap=&bmap;
-
- while (colorcount--) {
- rm[colorcount] = colormap[colorcount][0] >> 4L;
- gm[colorcount] = colormap[colorcount][1] >> 4L;
- bm[colorcount] = colormap[colorcount][2] >> 4L;
- if(CMFF && (colorcount < 16)) {
- rn[colorcount] = rm[colorcount];
- gn[colorcount] = gm[colorcount];
- bn[colorcount] = bm[colorcount];
- }
- }
-
- if(CMFF) nc = NCOL;
-
- for (i=0;i<Height;i++) /* process n lines/screen */
- for (plane=0;plane<Depth;plane++) { /* process n planes/line */
- destbuf=(UBYTE *)(bmap.Planes[plane])+linelen*i;
-
- if (bmhd.compression==cmpByteRun1) { /* compressed screen? */
- rowbytes=linelen;
-
- while (rowbytes) { /* unpack until 1 scan-line complete */
- n=*sourcebuf++; /* fetch block run marker */
-
- /* uncompressed block? copy n bytes verbatim */
- if (n>=0) {
- movmem(sourcebuf,destbuf,(unsigned int)++n); rowbytes-=n;
- destbuf+=n; sourcebuf+=n;
- }
- else { /* compressed block? expand n duplicate bytes */
- n=-n+1; rowbytes-=n;
- setmem(destbuf,(unsigned int)n,(unsigned int)*sourcebuf++);
- destbuf+=n;
- }
-
- } /* finish unpacking line */
- }
- else { /* uncompressed? just copy */
- movmem(sourcebuf,destbuf,(unsigned int)linelen);
- sourcebuf+=linelen; destbuf+=linelen;
- }
- } /* finish interleaved planes, lines */
- return(1);
- } /* end ReadILBM */
-