page@swan.ulowell.edu (Bob Page) (10/20/88)
Submitted-by: edavies@uvvm.bitnet (Eric Davies) Posting-number: Volume 2, Issue 2 Archive-name: graphics/surf.1of3 Surf is a program for producing bezier surfaces of revolution. It produces awesome pictures of wine glasses and doorknobs, and other objects one could turn on a lathe. Surf includes the capacity to map iff image files onto any surface that it can draw. # This is a shell archive. Remove anything before this line # then unpack it by saving it in a file and typing "sh file" # (Files unpacked will be owned by you and have default permissions). # This archive contains the following files: # ./menudef.c # ./menudef.h # ./menuexp.h # ./mergergb.c # ./mergergb.lnk # ./mouse.c # ./mytypes.h # ./packer.c # ./poly.c # ./poly.h # ./readilbm.c # ./readilbm.h # ./revolve.c # ./revolve.h # ./scrndef.c # ./scrndef.h # ./scrnio.c # ./scrnio.h # ./scrnio.ih # ./scrnops.c # ./surf.lnk # ./writeilbm.c # if `test ! -s ./menudef.c` then echo "writing ./menudef.c" cat > ./menudef.c << '\Rogue\Monster\' #include <exec/types.h> #include <exec/memory.h> #include <intuition/intuition.h> #include <graphics/gfxmacros.h> #ifdef MANX #include <functions.h> #endif #include "scrnio.h" #include "menudef.h" #include "scrndef.h" #include "poly.h" #include "readilbm.h" #define Selected(ax) ((ax).Flags & CHECKED) #include "menu_color.c" #include "menu_scrn.c" #include "menu_image.c" #include "menu_files.c" struct Menu menu[] ={ { &menu[1], /* next menu */ 8, 0, /* x, y */ 6*8, 10, /* w,h */ MENUENABLED, (BYTE *)"File", fileitems, 0,0,0,0 }, { &menu[2], /* next menu */ 7*8, 0, /* x, y */ 6*8, 10, /* w,h */ MENUENABLED, (BYTE *)"Color", coloritems, 0,0,0,0 }, { &menu[3], /* next menu */ 14*8,0, /* x, y */ 7*8, 10, /* w,h */ MENUENABLED, (BYTE *)"Screen", scrnitems, 0,0,0,0 }, { NULL, /* next menu */ 22*8,0, /* x, y */ 6*8, 10, /* w,h */ MENUENABLED, (BYTE *)"Image", imageitems, 0,0,0,0 } }; void MenuHandler(code) USHORT code; { if( code == 0xffff ) { /* invalid menu pick */ return; } switch( MENUNUM(code)) { case 0: /* write ilbm */ MenuDoFile(ITEMNUM(code)); break; case 1: /* set screen color */ MenuSetColMap(); break; case 2: /* set screen type */ MenuSetScrn(); break; case 3: /* set image stuff */ MenuSetImage(); break; default: break; } } \Rogue\Monster\ else echo "will not over write ./menudef.c" fi if `test ! -s ./menudef.h` then echo "writing ./menudef.h" cat > ./menudef.h << '\Rogue\Monster\' extern struct Menu menu[]; extern void MenuHandler(/* USHORT */); \Rogue\Monster\ else echo "will not over write ./menudef.h" fi if `test ! -s ./menuexp.h` then echo "writing ./menuexp.h" cat > ./menuexp.h << '\Rogue\Monster\' #ifndef MENUEXP_H_FILE #define MENUEXP_H_FILE #ifndef INTUITION_INTUITION_H #include <intuition/intuition.h> #endif INTUITION_INTUITION_H extern USHORT *AbortDrawPtr; extern USHORT *DebugOnPtr; #define AbortDraw (*AbortDrawPtr & CHECKED) #define ClrAbort() { *AbortDrawPtr &= ~CHECKED; } #define DebugOn (*DebugOnPtr & CHECKED) #endif MENUEXP_H_FILE \Rogue\Monster\ else echo "will not over write ./menuexp.h" fi if `test ! -s ./mergergb.c` then echo "writing ./mergergb.c" cat > ./mergergb.c << '\Rogue\Monster\' /* * This program, when called with arg "smith", tries to read smith.r, smith.g * and smith.b, and write a combined raw data file acceptable to RAY2, called * smith.tmp */ #include <stdio.h> #include "mytypes.h" #define RED 0 #define GRN 1 #define BLU 2 #define NumPrims 3 /* number of primary colors */ #define MakeID(a,b,c,d) ( ((a)<<24) | ((b)<<16) | ((c)<<8) | (d) ) #define ID_FORM MakeID('F','O','R','M') #define ID_ILBM MakeID('I','L','B','M') #define ID_BMHD MakeID('B','M','H','D') #define ID_CMAP MakeID('C','M','A','P') #define ID_CAMG MakeID('C','A','M','G') #define ID_BODY MakeID('B','O','D','Y') #define ROUNDUP(x) ( ((x)+1) & (~1L) ) struct CHUNK { unsigned long Id, Size; } Chunk; struct BMHD { short w,h,x,y; char npl,mask,compress,pad1; short transparentColor; char xAspect,yAspect; short pageWidth,pageHeight; }; /* * compare width and height of two bit maps * return false if equal */ bool CmpBMHD(a, b) struct BMHD *a, *b; { return( a->w != b->w || a->h != b->h || a->npl != b->npl ); } struct BMHD bmhd[NumPrims]; static FILE *ftrip[NumPrims], *fout; char *nametrip[NumPrims]; char *oname; bool FileError; short depth; unsigned char colmap[NumPrims][32][3]; /* * read len bytes from selected file */ void FRead(buffer, len, filenum) char *buffer; int len, filenum; { if( fread(buffer, len, 1, ftrip[filenum]) == 0 ) { fprintf(stderr, "read error in %s\n", nametrip[filenum] ); exit(-1); } } #define ABORT(str) { fprintf(stderr,str); exit(-1); } #define ReadChunk() FRead(&Chunk, sizeof(Chunk), filenum) void ReadIffHeaders(filenum) int filenum; { long ILBMid; bool cmapFlag = false, bmhdFlag = false; short i; ReadChunk (); if (Chunk.Id != ID_FORM) ABORT ("Not an IFF File"); FRead (&ILBMid, 4, filenum); if (ILBMid != ID_ILBM) ABORT ("Not an ILBM File"); while (1) { long camgdata; ReadChunk (); if (Chunk.Id == ID_BODY) { if (!cmapFlag) { printf("no cmap before body in %s\n", nametrip[filenum]); FileError = true; } if (!bmhdFlag) { printf("no bmhd before the body in %s\n", nametrip[filenum]); FileError = true; } return; } if( feof( ftrip[filenum] ) ) { printf("reached end of file without seeing body in %s\n", nametrip[filenum]); FileError = true; return; } switch (Chunk.Id) { case ID_CMAP: FRead (colmap[filenum], Chunk.Size, filenum); for (i = 0; i < 32; i++) { colmap[filenum][i][filenum] >>= 4; } cmapFlag = true; break; case ID_BMHD: FRead(&bmhd[filenum], Chunk.Size, filenum); bmhdFlag = true; break; case ID_CAMG: FRead( &camgdata, sizeof(camgdata),filenum ); break; default: /* unknown identifier */ fseek( ftrip[filenum], Chunk.Size, 1); break; } } } /* * leftmost pixel of byte is in most significant bit of byte */ static char GetIlbmVal( rastlist, h) char *rastlist[6]; int h; { int i; char value = 0; short mask, bytep; mask = 0x80 >> ( h & 7); bytep = h >> 3; for( i = depth-1; i >= 0; i-- ) { value <<= 1; value |= (*(rastlist[i]+bytep) & mask) ? 1: 0; } return( value ); } /* * decompress a runlength row of bytes */ static void ReadDecomLine(linebytes, rp, filenum) int linebytes, filenum; char *rp; { int runlen; char pixel; while (linebytes) { runlen = getc (ftrip[filenum]); if (runlen > 127) runlen -= 256; if (runlen >= 0) { runlen++; FRead (rp, runlen, filenum); rp += runlen; linebytes -= runlen; } else { runlen = -runlen + 1; linebytes -= runlen; pixel = getc (ftrip[filenum]); do *(rp++) = pixel; while (--runlen); } } } /* * read raster line from one of the color files */ void LoadRaster(raster, ByteWidth, filenum) char *raster[6]; int ByteWidth, filenum; { if(bmhd[filenum].compress = 0) { FRead (raster, ByteWidth * depth, filenum); } else { short i; for( i = 0; i < depth; i++) { ReadDecomLine( ByteWidth, raster[i], filenum); } } } /* * write intensity values for a given gun * note: I've made dirty assumption about byte ordering in a short word * if you run this on an ibm (ha ha ha) you'll have to change it */ #define ChipSize 4 void SaveRaster( raster, width, prim) char *raster[]; int width, prim; { short i, j; unsigned short val; for( i = 0; i < width; i += ChipSize ) { val = colmap[prim][GetIlbmVal(raster, i+3)][prim] << ChipSize; val |= colmap[prim][GetIlbmVal(raster, i+2)][prim]; fputc( val&0xff, fout); val = colmap[prim][GetIlbmVal(raster, i+1)][prim] << ChipSize; val |= colmap[prim][GetIlbmVal(raster, i+0)][prim]; fputc( val&0xff, fout); } } /* * translate body of file to format RAY2 likes */ void TranslateRay2Body() { int BytesWidth; int row, height, width, plane, prim; char *raster[6]; depth = bmhd[0].npl; width = bmhd[0].w; height = bmhd[0].h; BytesWidth = (width + 7)/8 ; for( plane = 0; plane < bmhd[0].npl; plane++ ) { raster[plane] = (char *)malloc(BytesWidth); } for( row = 0; !FileError && row < height; row++ ) { fputc((unsigned char)(row>>8),fout); /* write line number */ fputc((unsigned char)(row&0xff),fout); for( prim = RED; prim <= BLU; prim++ ) { LoadRaster( raster, BytesWidth, prim); SaveRaster( raster, width, prim); } } } main(argc, argv) int argc; char *argv[]; { char buff[4][80]; char *extensions = "rgb"; int i; if( argc == 1 || *argv[1] == '?' ) { fprintf(stderr,"usage: merge filename\n"); exit(-1); } FileError = false; for( i = 0; i < NumPrims; i++ ) { sprintf(buff[i], "%s.%c", argv[1], extensions[i]); nametrip[i] = buff[i]; ftrip[i] = fopen(nametrip[i],"r"); if(!ftrip[i]) { fprintf(stderr,"unable to read %s\n", nametrip[i]); FileError = true; } } sprintf(buff[3], "%s.tmp", argv[1]); oname = (argc>2)? argv[2]: buff[3]; fout = fopen( oname,"w"); if(!fout) { fprintf(stderr,"unable to write to %s\n", oname); FileError = true; } if( FileError ) goto ErrorExit; for( i = 0; i < NumPrims; i++ ) { printf("reading header %d\n", i); ReadIffHeaders(i); } for( i = 1; i < NumPrims; i++ ) { if( CmpBMHD(&bmhd[0], &bmhd[i])) { fprintf(stderr,"image sizes differ(r != %d)\n", i); FileError = true; } } if( FileError ) goto ErrorExit; printf("about to translate body\n"); TranslateRay2Body(); ErrorExit: for( i = 0; i < NumPrims; i++) { if(ftrip[i]) fclose( ftrip[i] ); } if(fout) fclose(fout); } \Rogue\Monster\ else echo "will not over write ./mergergb.c" fi if `test ! -s ./mergergb.lnk` then echo "writing ./mergergb.lnk" cat > ./mergergb.lnk << '\Rogue\Monster\' ROOT lib:c.o MergeRGB.o LIBRARY LIB:lc.lib Lib:lcm.lib LIB:amiga.lib TO MergeRGB verbose nodebug \Rogue\Monster\ else echo "will not over write ./mergergb.lnk" fi if `test ! -s ./mouse.c` then echo "writing ./mouse.c" cat > ./mouse.c << '\Rogue\Monster\' #include "scrnio.ih" #ifdef MANX #include <functions.h> #endif #include "scrnio.h" #include "mytypes.h" #include "bezpt.h" #include "control.h" static bool buttondown; /* is left button down */ static short mousex, mousey; static bool isleftbut; /* left button or pseudo middle button */ void HandleTicks(mesg) struct IntuiMessage *mesg; { int x, y; x = CntrX(mesg->MouseX); y = CntrY(mesg->MouseY); if(!buttondown || (mousex == x && mousey == y )){ return; } mousex = x; mousey = y; switch( CurMode ) { case DRAWPOLY: EditBezPt( mousex, mousey); break; case FITBEZIER: /* * need to select between the two */ if( isleftbut ) { EditControl0(mousex, mousey); } else { EditControl1(mousex, mousey); } break; default: break; } } void HandleMButtons(mesg) struct IntuiMessage *mesg; { long leftdist, rightdist; long tx, ty; mousex = CntrX(mesg->MouseX); mousey = CntrY(mesg->MouseY); switch( mesg->Code) { case SELECTDOWN: buttondown = true; /* down */ switch( CurMode ) { case DRAWPOLY: InitBezPt( mousex, mousey); if( GetNumSegs() == 0 ) { InitBezPt( mousex, mousey ); } break; case FITBEZIER: tx = mousex - Cntrl1X(GetCurSeg()); ty = mousey - Cntrl1Y(GetCurSeg()); leftdist = tx *tx + ty * ty; tx = mousex - Cntrl2X(GetCurSeg()); ty = mousey - Cntrl2Y(GetCurSeg()); rightdist = tx *tx + ty * ty; if( isleftbut = (leftdist <= rightdist) ) { EditControl0( mousex, mousey ); } else { EditControl1( mousex, mousey ); } break; default: break; } break; case SELECTUP: buttondown = false; /* up */ break; case MENUUP: if( CurMode == FITBEZIER ) { DrawControl0(); DrawControl1(); NextSeg(); DrawControl0(); DrawControl1(); } break; default: break; } } \Rogue\Monster\ else echo "will not over write ./mouse.c" fi if `test ! -s ./mytypes.h` then echo "writing ./mytypes.h" cat > ./mytypes.h << '\Rogue\Monster\' #ifndef MYTYPES_H_FILE #define MYTYPES_H_FILE #define true 1 #define false 0 typedef char bool; extern char *calloc(), *malloc(); #define null 0L #ifndef MANX #include "exec/types.h" #include "libraries/mathffp.h" #define ceil SPCeil #define floor SPFloor #define fabs SPAbs #endif #endif MYTYPES_H_FILE \Rogue\Monster\ else echo "will not over write ./mytypes.h" fi if `test ! -s ./packer.c` then echo "writing ./packer.c" cat > ./packer.c << '\Rogue\Monster\' /* * this file is a hacked up version of the original, who blurb is below * changes made: internal buffer no longer static, but is now on stack */ /*----------------------------------------------------------------------* * packer.c Convert data to "cmpByteRun1" run compression. 11/15/85 * * By Jerry Morrison and Steve Shaw, Electronic Arts. * This software is in the public domain. * * control bytes: * [0..127] : followed by n+1 bytes of data. * [-1..-127] : followed by byte to be repeated (-n)+1 times. * -128 : NOOP. * * This version for the Commodore-Amiga computer. *----------------------------------------------------------------------*/ #include <exec/types.h> #define DUMP 0 #define RUN 1 #define MinRun 3 #define MaxRun 128 #define MaxDat 128 static short putSize; #define GetByte() (*source++) #define PutByte(c) { *dest++ = c; ++putSize; } static BYTE *buf; /* [TBD] should be 128? on stack?*/ static BYTE *PutDump(dest, nn) BYTE *dest; int nn; { int i; PutByte(nn-1); for(i = 0; i < nn; i++) PutByte(buf[i]); return(dest); } static BYTE *PutRun(dest, nn, cc) BYTE *dest; int nn, cc; { PutByte(-(nn-1)); PutByte(cc); return(dest); } #define OutDump(nn) dest = PutDump(dest, nn) #define OutRun(nn,cc) dest = PutRun(dest, nn, cc) /*----------- PackRow --------------------------------------------------*/ /* Given POINTERS TO POINTERS, packs one row, updating the source and destination pointers. RETURNs count of packed bytes.*/ int PackRow(source, dest, rowSize) BYTE *source, *dest; int rowSize; { char innerbuf[256]; char c,lastc = '\0'; BOOL mode = DUMP; short nbuf = 0; /* number of chars in buffer */ short rstart = 0; /* buffer index current run starts */ /* * cute way to make local buffer known to external procedures * since static variables increase executable size in Manx */ buf = innerbuf; /* way to put make local buffer known to external procs */ putSize = 0; buf[0] = lastc = c = GetByte(); /* so have valid lastc */ nbuf = 1; rowSize--; /* since one byte eaten.*/ for (; rowSize; --rowSize) { buf[nbuf++] = c = GetByte(); switch (mode) { case DUMP: /* If the buffer is full, write the length byte, then the data */ if (nbuf>MaxDat) { OutDump(nbuf-1); buf[0] = c; nbuf = 1; rstart = 0; break; } if (c == lastc) { if (nbuf-rstart >= MinRun) { if (rstart > 0) OutDump(rstart); mode = RUN; } else if (rstart == 0) mode = RUN; /* no dump in progress, so can't lose by making these 2 a run.*/ } else rstart = nbuf-1; /* first of run */ break; case RUN: if ( (c != lastc)|| ( nbuf-rstart > MaxRun)) { /* output run */ OutRun(nbuf-1-rstart,lastc); buf[0] = c; nbuf = 1; rstart = 0; mode = DUMP; } break; } lastc = c; } switch (mode) { case DUMP: OutDump(nbuf); break; case RUN: OutRun(nbuf-rstart,lastc); break; } return(putSize); } \Rogue\Monster\ else echo "will not over write ./packer.c" fi if `test ! -s ./poly.c` then echo "writing ./poly.c" cat > ./poly.c << '\Rogue\Monster\' #include <math.h> #include "mytypes.h" #include "scrnio.h" #include "bezpt.h" #include "revolve.h" #include "control.h" #include "poly.h" #include "readilbm.h" #include "menuexp.h" bool SpecOn = false; /* specular lighting enable - default off */ float Ambience = DefAmbience; float PtIntensity = (float)DefIntensity; float Kd = DefKd, Ks = DefKs; Pt3 LightSrc = { DefLightSrcX, DefLightSrcY, DefLightSrcZ }; static Rhomboid *polylist = null, *nextpoly; MapRhomboid *mpolylist = null, *mnextpoly; static int polyspace = 0; static bool shadeflag; long CalcMaxPolyNum() { return( GetNumSegs() * BezMesh * RevMesh ); } static bool PrepPoly() { if( polylist ) free( (char *)polylist ); polylist = (Rhomboid *)malloc( CalcMaxPolyNum() * sizeof(Rhomboid)); if( !polylist ) { OutErr("PrepPoly: not enough memory"); return( true ); } nextpoly = polylist; return(false); /* success = 0 */ } static bool PrepMPoly() { if( mpolylist ) free( (char *)mpolylist ); mpolylist = (MapRhomboid *) malloc( CalcMaxPolyNum() * sizeof(MapRhomboid)); if( !mpolylist ) { OutErr("PrepPoly: not enough memory"); return( true ); } mnextpoly = mpolylist; return(false); /* success = 0 */ } /* * Multiply a vector by scalar quantity */ void ScaleVec( fact, src, dst ) float fact; Pt3 *src, *dst; { dst->x = src->x * fact; dst->y = src->y * fact; dst->z = src->z * fact; } /* * convert a vector to a unitized vector * if possible */ void Unitize( vec ) Pt3 *vec; { float len; len = vec->x*vec->x + vec->y*vec->y + vec->z*vec->z; len = sqrt( len ); if( len != 0.0 ) { vec->x /= len; vec->y /= len; vec->z /= len; } } /* * calculate a vector from two points */ void CalcVector( src1, src2, dest ) Pt3 *src1, *src2, *dest ; { dest->x = src1->x - src2->x; dest->y = src1->y - src2->y; dest->z = src1->z - src2->z; } /* * calculate a normal from a list of polygons. This routine does the * logical trick of trying to exclude each point in turn if the * normal can not be calculated, or something of the sort. * a value of true is returned if a normal with a nonzero z component * could not be calculated */ bool CalcNormal( vxlist, normal) PtGen *vxlist[]; register Pt3 *normal; { int i, k, m; Pt3 *j[3]; Pt3 v1, v2; for( i = 0; i < RhomVxNum; i++ ) { for( k = 0, m = 3; m--; k++ ) { if( k == i ) { k++; } j[m] = &vxlist[k]->d3; } CalcVector( j[1], j[0], &v1 ); CalcVector( j[2], j[1], &v2 ); normal->z = v1.x*v2.y - v1.y*v2.x; if( normal->z == 0 ) { continue; } normal->x = v1.y*v2.z - v1.z*v2.y; normal->y = v1.z*v2.x - v1.x*v2.z; if( normal->z < 0 ) { normal->x = -normal->x; normal->y = -normal->y; normal->z = -normal->z; } Unitize(normal); return( false ); } return(true); } /* * Euclidean dot product. * I wonder what the minkowski dot product would look like */ float DotProd( v1, v2 ) Pt3 *v1, *v2; { return( v1->x*v2->x + v1->y*v2->y + v1->z*v2->z ); } /* * define a polygon as a set of four points * returns true if polygon created */ static bool CreatePoly(curpoly, p0, p1, p2, p3) register Rhomboid *curpoly; PtGen *p0, *p1, *p2, *p3; { Pt3 normal; PtGen *list[RhomVxNum]; list[0] = p0; list[1] = p1; list[2] = p2; list[3] = p3; /* * compute stuff needed only if producing shaded image */ if( shadeflag ) { Pt3 lvec; Pt3 center; float ptintens; float ldotn; /* light vector dot normal */ /* * if cant compute normal, then junk polygon */ if( CalcNormal( list, &normal )) { return(false); } curpoly->intensity = Ambience; center.x = ( list[0]->d3.x + list[1]->d3.x + list[2]->d3.x + list[3]->d3.x)/4.0; center.y = ( list[0]->d3.y + list[1]->d3.y + list[2]->d3.y + list[3]->d3.y)/4.0; center.z = ( list[0]->d3.z + list[1]->d3.z + list[2]->d3.z + list[3]->d3.z)/4.0; curpoly->depth = center.z; CalcVector( ¢er, &LightSrc, &lvec ); Unitize( &lvec ); ldotn = DotProd( &lvec, &normal ); if( ldotn < 0 ) { ptintens = PtIntensity * Kd * -ldotn; curpoly->intensity += ptintens; } /* * calculate specular component */ if( SpecOn && ldotn < 0 ) { float Kspec, Is; Pt3 rvec; /* lvec reflected through poly */ ScaleVec( 2*ldotn, &normal, &rvec ); CalcVector(&lvec, &rvec, &rvec ); Unitize( ¢er ); Kspec = DotProd( &rvec, ¢er); if( Kspec <= 0.0 ) { Is = Ks * Kspec * Kspec* PtIntensity; curpoly->intensity += Is; } } if( curpoly->intensity > 1.0 ) { curpoly->intensity = 1.0; } } else { /* * calculate depth of polygon * for now, try an average of the vertex depths */ curpoly->depth =( list[0]->d3.z + list[1]->d3.z + list[2]->d3.z + list[3]->d3.z)/4.0; } /* * store index to screen coordinates */ curpoly->pt[0] = p0->d2; curpoly->pt[1] = p1->d2; curpoly->pt[2] = p2->d2; curpoly->pt[3] = p3->d2; return(true); } /* * passable procedure for creating polygons without mapping */ static void AcceptPoly(p0, p1, p2, p3) PtGen *p0, *p1, *p2, *p3; { if( CreatePoly(nextpoly, p0, p1, p2,p3)) { nextpoly++; } } static void AcceptMPoly( p0, p1, p2, p3) PtGen *p0, *p1, *p2, *p3; { if( CreatePoly(&mnextpoly->rhom, p0, p1, p2,p3)) { mnextpoly->bezindex = RevImageB; mnextpoly->revindex = RevImageR; mnextpoly++; } } /* * compare the depth of two polygons for SortPoly */ static int CmpDepth( a, b ) Rhomboid *a, *b; { if( a->depth < b->depth ) return(-1); else if( a->depth > b->depth ) return(1); else return(0); } static int CmpMDepth( a, b ) MapRhomboid *a, *b; { if( a->rhom.depth < b->rhom.depth ) return(-1); else if( a->rhom.depth > b->rhom.depth ) return(1); else return(0); } void RevNoShade() { Rhomboid *i; if( GetNumSegs() < 1 ) { return; } CurMode = NOTACTIVE; ClrAbort(); shadeflag = false; if( PrepPoly() ) return; if( Revolve(AcceptPoly) ) return; qsort( (char *)polylist, nextpoly - polylist, sizeof(Rhomboid), CmpDepth); ClrWindow(false); for( i = polylist; i< nextpoly; i++ ) { if( AbortDraw ) return; DrawRhomFrame( i->pt ); } } void RevShade() { register Rhomboid *i; if( GetNumSegs() < 1 ) { return; } CurMode = NOTACTIVE; ClrAbort(); shadeflag = true; if( PrepPoly() || Revolve(AcceptPoly) ) { return; } qsort( (char *)polylist, nextpoly-polylist, sizeof(Rhomboid), CmpDepth); ClrWindow(false); for( i = polylist; i< nextpoly; i++ ) { if( AbortDraw ) return; DrawRhomShade( i ); } } void RevMap() { register MapRhomboid *i; if( GetNumSegs() < 1 ) { return; } if( InitMapping() ) { return; } ClrAbort(); CurMode = NOTACTIVE; shadeflag = true; if( PrepMPoly() || Revolve(AcceptMPoly) ) { return; } qsort( (char *)mpolylist, mnextpoly-mpolylist, sizeof(MapRhomboid), CmpMDepth); ClrWindow(false); for( i = mpolylist; i< mnextpoly; i++ ) { if( AbortDraw ) return; DrawRhomMap(i); } } \Rogue\Monster\ else echo "will not over write ./poly.c" fi if `test ! -s ./poly.h` then echo "writing ./poly.h" cat > ./poly.h << '\Rogue\Monster\' #ifndef POLY_H_FILE #define POLY_H_FILE #include <exec/types.h> #include "mytypes.h" #include "revolve.h" #define RhomVxNum 4 typedef struct { ScrnPair pt[RhomVxNum]; float depth; float intensity; } Rhomboid; typedef struct { Rhomboid rhom; short bezindex, revindex; } MapRhomboid; extern bool SpecOn; #define DefLightSrcX 0.0 #define DefLightSrcY 0.0 #define DefLightSrcZ 0.0 #define DefIntensity 0.8 #define DefAmbience 0.15 #define DefKd 0.8 #define DefKs 0.2 extern float Ambience, PtIntensity, Kd, Ks; extern Pt3 LightSrc; extern void RevNoShade(); extern void RevShade(); extern void RevMap(); #endif !POLY_H_FILE \Rogue\Monster\ else echo "will not over write ./poly.h" fi if `test ! -s ./readilbm.c` then echo "writing ./readilbm.c" cat > ./readilbm.c << '\Rogue\Monster\' #include <stdio.h> #include <ctype.h> #include "readilbm.h" #define FALSE 0 #define TRUE 1 #define RED 0 #define GRN 1 #define BLU 2 /* color to grey conversion methods */ #define AVERAGE 0 #define LUMIN 1 #define DIST 2 #define REDONLY 3 #define GREENONLY 4 #define BLUEONLY 5 #define MakeID(a,b,c,d) ( ((a)<<24) | ((b)<<16) | ((c)<<8) | (d) ) #define ID_FORM MakeID('F','O','R','M') #define ID_ILBM MakeID('I','L','B','M') #define ID_BMHD MakeID('B','M','H','D') #define ID_CMAP MakeID('C','M','A','P') #define ID_CAMG MakeID('C','A','M','G') #define ID_BODY MakeID('B','O','D','Y') #define ROUNDUP(x) ( ((x)+1) & (~1L) ) static struct CHUNK { unsigned long Id, Size; } Chunk; static unsigned char cmap[32][3]; struct BMHD { short w,h,x,y; char npl,mask,compress,pad1; short transparentColor; char xAspect,yAspect; short pageWidth,pageHeight; }; static short Color[32], /* output colors */ Method = AVERAGE; /* color conversion */ static short numcolors; static FILE *fin; /* input file */ extern char *malloc(); static void FRead(); static void ReadBMHD(); static void ReadChunk(); static void RastOut(); static void HamOut(); static char GetIlbmVal(); static void InitColorMappings(); static short Convert(); static void ReadDecomLine(); static void ProcessRows(); #define ABORT(str) { OutErr(str); goto ErrorExit; } void SetGreyModel( model ) int model; { Method = model; } /* * main routine for reading in an iff file */ void ReadIlbm(filename) char *filename; { struct BMHD bmhd; long ILBMid; unsigned char cmapFlag = FALSE, bmhdFlag = FALSE; if ((fin = fopen (filename, "r")) == NULL) { OutErr ("ERROR: cannot open input file"); return; } /* read in iff file */ ReadChunk (); if (Chunk.Id != ID_FORM) ABORT ("Not an IFF File"); FRead (&ILBMid, 4); if (ILBMid != ID_ILBM) ABORT ("Not an ILBM File"); while (1) { long camgdata; ReadChunk (); if (Chunk.Id == ID_BODY) break; if( feof( fin ) ) { ABORT("reached end of file without seeing body\n"); } switch (Chunk.Id) { case ID_CMAP: FRead (cmap, Chunk.Size); numcolors = Chunk.Size/3; cmapFlag = TRUE; break; case ID_BMHD: ReadBMHD (&bmhd); bmhdFlag = TRUE; break; case ID_CAMG: FRead( &camgdata, sizeof(camgdata) ); break; default: /* unknown identifier */ fseek( fin, Chunk.Size, 1); break; } } if (!cmapFlag) { ABORT("IFF file does not contain a CMAP chunk before the BODY\n"); } if (!bmhdFlag) { ABORT("IFF file does not contain a BMHD chunk before the BODY\n"); } InitColorMappings(); if( OpenImgPix( bmhd.w, bmhd.h, Convert(0xf, 0xf, 0xf)) ) { ProcessRows(&bmhd); } ErrorExit: fclose( fin); } static void ProcessRows(bmhd) struct BMHD *bmhd; { char *rastlist[6]; char *Raster; int depth, i, v, pixwidth; int BytePerLine; depth = bmhd->npl; pixwidth = bmhd->w; BytePerLine =(pixwidth+7) / 8; Raster = (char *) malloc (BytePerLine * depth); if(!Raster ) { OutErr("ProcessRows:could not allocate Raster"); return; } for( i = 0; i < depth; i++ ) { rastlist[i] = Raster + BytePerLine*i; } for( v = 0; v < bmhd->h; v++) { switch (bmhd->compress) { case 0: FRead (Raster, BytePerLine * depth); break; case 1: for( i = 0; i < depth; i++) { ReadDecomLine( BytePerLine, rastlist[i]); } break; default: ABORT ("Unknown Compression type in BODY"); } if(depth == 6 ) { HamOut( rastlist, pixwidth, v); } else { RastOut( rastlist, pixwidth, v, depth); } } ErrorExit: if( Raster ) free(Raster); } static void ReadDecomLine(linebytes, rp) int linebytes; char *rp; { int runlen; char pixel; while (linebytes) { runlen = getc (fin); if (runlen > 127) runlen -= 256; if (runlen >= 0) { runlen++; FRead (rp, runlen); rp += runlen; linebytes -= runlen; } else { runlen = -runlen + 1; linebytes -= runlen; pixel = getc (fin); do *(rp++) = pixel; while (--runlen); } } } /* * Convert - convert (r,g,b) to hex greyscale. */ static short Convert(r,g,b) unsigned char r,g,b; { short i, rd, gd, bd, min, dist, best; /* convert color according to 'Method' */ switch (Method) { case AVERAGE: /* average r,g,b to obtain grey level */ return ((r + g + b) / 3); case LUMIN: /* use NTSC luminescence as grey level */ return ((r * 30 + g * 59 + b * 11) / 100); case DIST: /* use grey with minimum distance in color */ min = 15*15 * 3; for( i = 0; i < numcolors; i++ ) { rd = r -i; gd = g - i; bd = b - i; dist = rd * rd + gd * gd + bd * bd; if( dist < min ) { min = dist; best = i; } } return( best ); case REDONLY: return(r); case GREENONLY: return(g); case BLUEONLY: return(b); } } /* Convert */ static void InitColorMappings() { int i; /* put colors in 4-bit range and Convert */ for (i = 0; i < 32; i++) { cmap[i][RED] >>= 4; cmap[i][GRN] >>= 4; cmap[i][BLU] >>= 4; Color[i] = Convert (cmap[i][RED], cmap[i][GRN], cmap[i][BLU]); } } /* * leftmost pixel of byte is in most significant bit of byte */ static char GetIlbmVal( rastlist, h, bpp ) char *rastlist[6]; int h, bpp; { int i; char value = 0; short mask, bytep; mask = 0x80 >> ( h & 7); bytep = h >> 3; for( i = bpp-1; i >= 0; i-- ) { value <<= 1; value |= (*(rastlist[i]+bytep) & mask) ? 1: 0; } return( value ); } /* * HamOut - output ham image in hex. */ static void HamOut(rastlist, pixwidth, v) char *rastlist[6]; int pixwidth, v; { unsigned char lastred = 0, lastgreen = 0, lastblue = 0; int h; char pixval; for( h = 0; h <pixwidth; h++ ) { short shade; shade = GetIlbmVal(rastlist, h, 6); pixval = shade & 0x0F; switch (shade & 0x30) { case 0x00: lastred = cmap[pixval][RED]; lastgreen = cmap[pixval][GRN]; lastblue = cmap[pixval][BLU]; shade = Color[pixval]; break; case 0x10: lastblue = pixval; shade = Convert(lastred,lastgreen,lastblue); break; case 0x20: lastred = pixval; shade = Convert(lastred,lastgreen,lastblue); break; case 0x30: lastgreen = pixval; shade = Convert(lastred,lastgreen,lastblue); } SetImgPix(h, v, shade); } } /* * RastOut - handle normal bit mapped images */ static void RastOut(rastlist, pixwidth, v, depth) char *rastlist[6]; int pixwidth, v, depth; { int h, bit; for( h = 0; h < pixwidth; h++ ) { short shade; shade = Color[GetIlbmVal( rastlist, h, depth)]; SetImgPix( h, v, shade); } } /* * ReadChunk - read in an IFF Chunk. */ static void ReadChunk() { FRead (&Chunk, sizeof (Chunk)); } /* ReadChunk */ /* * ReadBMHD - read the BMHD structure. */ static void ReadBMHD(bmhd) struct BMHD *bmhd; { FRead (bmhd, Chunk.Size); } /* ReadBMHD */ /* * FRead - read 'len' bytes to 'pointer' while checking for an error. */ static void FRead(pointer,len) char *pointer; int len; { if (fread (pointer, len, 1, fin) == 0) { char outbuff[90]; sprintf(outbuff,"Fread Error in reading input file at %d ", ftell(fin)); OutErr(outbuff); } } /* FRead */ \Rogue\Monster\ else echo "will not over write ./readilbm.c" fi if `test ! -s ./readilbm.h` then echo "writing ./readilbm.h" cat > ./readilbm.h << '\Rogue\Monster\' #ifndef READILBM_H_FILE #define READILBM_H_FILE #ifndef MYTYPES_H_FILE #include "mytypes.h" #endif MYTYPES_H_FILE #define DefRepV 1 #define DefRepH 1 /* * how many times the image should be replicated on screen */ extern short MapRepV, MapRepH; /* * Size of image read in */ extern int MapImageV, MapImageH; /* * ReadPixel returns an intensity between 0-255 */ extern short GetImgPix(/* short vert, hori */); extern void CloseImgPix(); bool OpenImgPix( /* int sizex, sizey; short maxshade */); void SetImgPix( /* int x, y; short val */ ); short GetImgPix( /* int x, y */); extern void PrepImgPix(/* void */); #define DefXYFlip false extern void FlipImgPix( /* bool flip */); extern void SetGreyModel( /* int */); #endif READILBM_H_FILE \Rogue\Monster\ else echo "will not over write ./readilbm.h" fi if `test ! -s ./revolve.c` then echo "writing ./revolve.c" cat > ./revolve.c << '\Rogue\Monster\' #include <math.h> #include "fasttrig.h" #include "bezpt.h" #include "revolve.h" #include "mytypes.h" RevAxisType RevAxis; short RevMesh = DefRevMeshVal; short RevImageR, /* revolution index */ RevImageB; /* bezier index */ static int RotRange = DefRotRange; static int RotStart = DefRotStart; static int SecAngle = DefTilt; static float SurfDist = DefSurfDist; static float ViewDist = DefViewDist; static bool Perspective = DefPersp; void SetPerspective( value) int value; { Perspective = value; } void SetRevAxis( value) int value; { RevAxis = (value)? RevY : RevX; } void SetRotStart( value ) int value; { RotStart = value; } void SetRotRange( value ) int value; { RotRange = value; } void SetSecAng( value ) int value; { SecAngle = value; } void SetRevMesh( value ) int value; { RevMesh = value; } void SetSurfDist( value ) int value; { SurfDist = (float )value; } void SetViewDist( value ) int value; { ViewDist = (float )value; } static float secsin, seccos; /* trig values of secondary angle */ static int sizeptlist = 0; static PtGen *ptlist1 = 0, *ptlist2 = 0; static int NumEnts; /* number of angle slices */ static bool PrepRev() { NumEnts = RevMesh+1; /* * allocate space 3d descriptions of a point revolved x degrees */ if( NumEnts > sizeptlist ) { if( ptlist1 ) free(ptlist1); if( ptlist2 ) free(ptlist2); ptlist1 =(PtGen *) malloc( NumEnts * sizeof(PtGen) ); ptlist2 =(PtGen *) malloc( NumEnts * sizeof(PtGen) ); if( !ptlist1 || !ptlist2 ) { OutErr("PrepRev:not enough memory"); return(true); } } if( InitFastTrig( RotStart, RotRange, NumEnts)) return(true); secsin = sin((float)SecAngle*PI/180); seccos = cos((float)SecAngle*PI/180); return (false); } static void CalcRing(ptlist, xpos, ypos) register PtGen *ptlist; float xpos, ypos; { int angle; for( angle = 0; angle < NumEnts; angle++, ptlist++) { float temp; /* * calculate 3d coordinate of point revolved */ if( RevAxis == RevX) { ptlist->d3.y = ypos * fcos(angle); temp = ypos * fsin(angle); ptlist->d3.x = xpos* seccos - temp *secsin; ptlist->d3.z = xpos * secsin + temp * seccos; } else { ptlist->d3.x = xpos * fcos(angle); temp = xpos * fsin( angle); ptlist->d3.y = ypos * seccos + temp * secsin; ptlist->d3.z = secsin * ypos - temp * seccos; } ptlist->d3.z -= SurfDist; if( Perspective ) { float PerspScale; PerspScale = fabs(ViewDist / ptlist->d3.z); ptlist->d3.x *= PerspScale; ptlist->d3.y *= PerspScale; } /* * calculate the 2d screen coordinate equvalent */ /* ptlist->d2.x = (short) ptlist->d3.x; ptlist->d2.y = (short) ptlist->d3.y; */ ptlist->d2.x = (short) (ptlist->d3.x + 0.5); ptlist->d2.y = (short) (ptlist->d3.y + 0.5); } } /* * return true on failure */ bool Revolve(acceptfunc) void (*acceptfunc)(); { int segno; float tparm, deltat; int angle; int subseg; if( PrepRev() ) { return(true); } deltat = 1.0/BezMesh; RevImageB = 0; ResetActSeg(); do { float xpos, ypos; InitCalcBez(); xpos = StartPtX(GetCurSeg()); ypos = StartPtY(GetCurSeg()); CalcRing(ptlist1, xpos, ypos ); for( subseg = 1; subseg <= BezMesh; subseg++ ) { register PtGen *ptlista, *ptlistb; register int numpoly; tparm = subseg * deltat; if( subseg & 1 ) { ptlista = ptlist2; ptlistb = ptlist1; } else { ptlista = ptlist1; ptlistb = ptlist2; } CalcBezPt(tparm, &xpos, &ypos ); CalcRing( ptlista, xpos, ypos ); RevImageR = 0; for( numpoly = NumEnts -1; numpoly--; ) { /* (* acceptfunc)(ptlista, ptlista+1, ptlistb+1, ptlistb); */ (* acceptfunc)(ptlistb, ptlista, ptlista+1, ptlistb+1); ptlista++; ptlistb++; RevImageR++; } RevImageB++; } NextSeg(); } while( ActSeg ); return( false ); } \Rogue\Monster\ else echo "will not over write ./revolve.c" fi if `test ! -s ./revolve.h` then echo "writing ./revolve.h" cat > ./revolve.h << '\Rogue\Monster\' #ifndef REVOLVE_H_FILE #define REVOLVE_H_FILE #include "mytypes.h" typedef enum { RevX, RevY } RevAxisType; extern RevAxisType RevAxis; #define DefRevMeshVal 30 #define DefSurfDist 3000 #define DefTilt 15 #define DefRotRange 360 #define DefRotStart 0 #define DefPersp false #define DefViewDist 3000 typedef struct { short x, y; } ScrnPair; typedef struct { float x, y, z; } Pt3; typedef struct { Pt3 d3; ScrnPair d2; } PtGen; extern short RevMesh; extern short RevImageR, RevImageB; extern void SetRotStart(); extern void SetRotRange(/* Panel_item, int, struct input_event */); extern void SetSecAng(/* Panel_item, int, struct input_event */); extern void SetPolyMode( /* Panel_item, int, struct input_event */); extern void SetFitBez( /* Panel_item, int, struct input_event */); extern bool Revolve( /* Panel_item, int, struct input_event */); extern void SetRevAxis( /* Panel_item, int, struct input_event */); extern void SetRevMesh( /* Panel_item, int, struct input_event */); extern void SetSurfDist(/* Panel_item, int, struct input_event */); extern void SetViewDist(); extern void SetPerspective(); #endif !REVOLVE_H_FILE \Rogue\Monster\ else echo "will not over write ./revolve.h" fi if `test ! -s ./scrndef.c` then echo "writing ./scrndef.c" cat > ./scrndef.c << '\Rogue\Monster\' /* this file contains definition for the screen */ #include <exec/types.h> #include <intuition/intuition.h> #include <graphics/gfxmacros.h> #ifdef MANX #include <functions.h> #endif #include "scrndef.h" struct TextAttr myfont1 = { (UBYTE *)"topaz.font", 8, 0, 0 }; struct NewScreen SurfScrnDef = { 0,0, /* left and top edge */ SurfInitW, SurfInitH+ButHeight, /* width and height */ SurfInitD, /* num bitplanes bit planes */ 0,1, /* detail, block pen */ SurfInitType, /* lores non interlaced */ CUSTOMSCREEN, &myfont1, NULL /*(UBYTE *) "Screen" */, NULL, NULL }; struct NewWindow SurfWinDef = { 0, ButHeight, /* left, top */ SurfInitW, SurfInitH, /* width, height */ -1, -1, /* default detail and block pen */ MOUSEBUTTONS | MOUSEMOVE| INTUITICKS /* | CLOSEWINDOW */, RMBTRAP | SIMPLE_REFRESH | GIMMEZEROZERO | BORDERLESS | BACKDROP, NULL, NULL, /* gadget, checkmark */ NULL /* (UBYTE *) "BezSurf - By Eric Davies" */, NULL, /* pointer to screen */ NULL, /* pointer to super bitmap */ 10, 10, 640, 200, /* min and max dimensions */ CUSTOMSCREEN }; struct NewWindow GadWinDef = { 0, 0, /* left, top */ SurfInitW, ButHeight, /* width, height */ -1, 0, /* default detail and block pen */ GADGETUP, SIMPLE_REFRESH | BORDERLESS | BACKDROP, NULL, NULL, /* gadget, checkmark */ NULL /*(UBYTE *) "Gadwin" */, NULL, /* pointer to screen */ NULL, /* pointer to super bitmap */ 10, 10, 10, 10, /* min and max dimensions */ CUSTOMSCREEN }; struct NewWindow CntrlWinDef = { 0, 0, /* left, top */ 640, 180, /* width, height */ -1, -1, /* default detail and block pen */ CLOSEWINDOW| GADGETUP| MENUPICK, SIMPLE_REFRESH | WINDOWCLOSE | WINDOWDEPTH | WINDOWDRAG | WINDOWSIZING, NULL, NULL, /* gadget(set by program), checkmark */ (UBYTE *) "BezSurf - Control Panel - By Eric Davies", NULL, /* pointer to screen */ NULL, /* pointer to super bitmap */ 10, 10, 640, 200, /* min and max dimensions */ WBENCHSCREEN }; \Rogue\Monster\ else echo "will not over write ./scrndef.c" fi if `test ! -s ./scrndef.h` then echo "writing ./scrndef.h" cat > ./scrndef.h << '\Rogue\Monster\' #ifndef SCRNDEF_H_FILE #define SCRNDEF_H_FILE #define ButHeight 10 /* height of GadWin */ #define SurfInitW 320 /* initial width */ #define SurfInitH 200 /* initial height */ #define SurfInitD 4 /* 16 color */ #define SurfInitType 0 /* Lores */ extern struct NewWindow SurfWinDef; extern struct NewWindow CntrlWinDef; extern struct NewScreen SurfScrnDef; extern struct NewWindow GadWinDef; #endif !SCRNDEF_H_FILE \Rogue\Monster\ else echo "will not over write ./scrndef.h" fi if `test ! -s ./scrnio.c` then echo "writing ./scrnio.c" cat > ./scrnio.c << '\Rogue\Monster\' /* main program */ #include "scrnio.ih" /*#include <functions.h>*/ #include "scrndef.h" #include "scrnio.h" #include "gadgetdef.h" #include "menudef.h" struct Screen *SurfScrn = NULL; struct Window *SurfWin = NULL; struct Window *CntrlWin = NULL; struct Window *GadWin = NULL; /* * bit masks for waiting for signals */ short CntrlSigBit, SurfSigBit, GadSigBit; long SignalMask = 0; struct RastPort *rp; struct ViewPort *vp; struct Library *GfxBase = 0, *IntuitionBase = 0; int XOR = COMPLEMENT, /* so my other modules don't need to */ WRITE = JAM1; /* include so many amiga includes */ int WinHOrig, WinVOrig; int WinFgCol; int ColorMax; int NumColors; /* * data structures needed to use amiga polygons routines */ static WORD PolyArea[5*5]; static struct AreaInfo PolyInfo; static PLANEPTR PolyWorkSpace; static struct TmpRas PolyTmpRas; static void ResetWinDat() { WinHOrig = SurfWinDef.Width >>1; WinVOrig = SurfWinDef.Height >>1; rp = SurfWin->RPort; SetDrMd( rp, JAM1 ); } /* * open surface window/screen */ OpenSurf() { NumColors = 1 << SurfScrnDef.Depth; ColorMax = ( NumColors -1) * 8 + 1; WinFgCol = (NumColors - 1) & 0x1f; SurfScrnDef.BlockPen = ( WinFgCol *3) /4; SurfScrnDef.DetailPen = WinFgCol>>2; SurfScrn = OpenScreen( &SurfScrnDef ); MenuSetColMap(); SurfWinDef.Screen = GadWinDef.Screen = SurfScrn; SurfWinDef.Width = GadWinDef.Width = SurfScrnDef.Width; SurfWinDef.Height = SurfScrnDef.Height - ButHeight; SurfWin = OpenWindow( &SurfWinDef ); GadWin = OpenWindow( &GadWinDef ); SurfSigBit = SurfWin->UserPort->mp_SigBit; GadSigBit = GadWin->UserPort->mp_SigBit; SignalMask = (1<<CntrlSigBit) | (1<<SurfSigBit)| (1<<GadSigBit); ResetWinDat(); ShowTitle( SurfScrn, 0L ); /* hide screen title behind backdrop */ InitArea( &PolyInfo, PolyArea, 5); rp->AreaInfo = &PolyInfo; PolyWorkSpace = AllocRaster( SurfWinDef.Width, SurfWinDef.Height); if( !PolyWorkSpace ) { CloseDisplay(); perror("no space for temporary rastern"); exit(0); } else { InitTmpRas( &PolyTmpRas, PolyWorkSpace, RASSIZE( SurfWinDef.Width, SurfWinDef.Height )); rp->TmpRas = &PolyTmpRas; } } void InitWindow() { GfxBase = OpenLibrary("graphics.library",0); if( GfxBase == 0 ) { OutErr("graphics library won't open"); exit(10); } IntuitionBase = OpenLibrary("intuition.library",0); if( IntuitionBase == 0 ) { OutErr("intuition library won't open"); exit(10); } InitGadgets(); CntrlWin = OpenWindow( &CntrlWinDef ); CntrlSigBit = CntrlWin->UserPort->mp_SigBit; MenuSetScrn(); if( !SurfScrn || !SurfWin || !CntrlWin ) { OutErr("couldn't open at least one window or screen"); CloseDisplay(); exit( 0 ); } SetMenuStrip(CntrlWin, menu ); } /* * remove surface window/screen */ CloseSurf() { if( PolyWorkSpace) FreeRaster( PolyWorkSpace, SurfWinDef.Width, SurfWinDef.Height ); if( SurfWin ) CloseWindow( SurfWin ); if( GadWin ) CloseWindow( GadWin ); if( SurfScrn ) CloseScreen( SurfScrn ); } void CloseDisplay() { CloseSurf(); if( CntrlWin ) { ClearMenuStrip( CntrlWin ); CloseWindow( CntrlWin ); } EndGadgets(); if ( IntuitionBase ) CloseLibrary(IntuitionBase); if ( GfxBase ) CloseLibrary(GfxBase); } \Rogue\Monster\ else echo "will not over write ./scrnio.c" fi if `test ! -s ./scrnio.h` then echo "writing ./scrnio.h" cat > ./scrnio.h << '\Rogue\Monster\' extern void InitWindow(); extern void CloseDisplay(); extern void SetMono(); extern void ClearWindow(); extern void DrawPoly(); extern int WinHOrig, WinVOrig; extern int XOR, WRITE; extern short DitherMask; #define CntrX(XVAL) ((XVAL) - WinHOrig) #define CntrY(YVAL) (WinVOrig - (YVAL)) /* fudge for the mouse */ #define UCntrX(XVAL) ((XVAL) + WinHOrig) #define UCntrY(YVAL) (WinVOrig - (YVAL)) \Rogue\Monster\ else echo "will not over write ./scrnio.h" fi if `test ! -s ./scrnio.ih` then echo "writing ./scrnio.ih" cat > ./scrnio.ih << '\Rogue\Monster\' /* main program */ #include <exec/types.h> #include <intuition/intuition.h> #include <graphics/gfxmacros.h> extern struct Screen *SurfScrn; extern struct Window *SurfWin; extern struct Window *CntrlWin; extern struct Window *GadWin; extern long BackColor; /* * bit masks for waiting for signals */ extern short CntrlSigBit, SurfSigBit, GadSigBit; extern long SignalMask; extern struct RastPort *rp; extern struct ViewPort *vp; extern int WinFgCol; extern int ColorMax; extern int NumColors; extern UWORD GrayPat[9][4]; #define DefBkPlane 0 \Rogue\Monster\ else echo "will not over write ./scrnio.ih" fi if `test ! -s ./scrnops.c` then echo "writing ./scrnops.c" cat > ./scrnops.c << '\Rogue\Monster\' #include "scrnio.ih" #ifdef MANX #include <functions.h> #endif #include "scrndef.h" #include "scrnio.h" #include "gadgetdef.h" #include "menudef.h" #include "bezpt.h" #include "revolve.h" #include "control.h" #include "poly.h" long BackColor = DefBkPlane; short DitherMask = 7; void SetMono( maxrval, maxgval, maxbval ) short maxrval, maxgval, maxbval; { long i; short range; long rval, gval, bval; range = (NumColors -1) & 0x1f; /* max 32 colours */ for( i = 0; i <= range; i++ ) { rval = (maxrval * i )/range; gval = (maxgval * i )/range; bval = (maxbval * i )/range; SetRGB4( &(SurfScrn->ViewPort), i, rval, gval, bval ); } } void SetRainbow() { long i; short range; long rval, gval, bval; range = NumColors>> 1; /* * can't do a rainbow with only 2 colors */ if( range < 2) { return; } for( i = 0; i < range; i++ ) { long diff; diff = (0xf * i )/(range-1); rval = 0xf - diff; bval = diff; gval = 0xf; SetRGB4( &(SurfScrn->ViewPort), i, rval, gval, bval); } for( i = 0; i < range; i++ ) { long diff; diff = (0xf * i )/(range-1); rval = diff; bval = 0xf; gval = 0xf - diff; SetRGB4( &(SurfScrn->ViewPort), i+range, rval, gval, bval); } SetRGB4( &(SurfScrn->ViewPort), 0L, 0L, 0L, 0L); } /* * set colours for hourglass pointer */ SetHourGlassCol() { SetRGB4( &(SurfScrn->ViewPort),17L, 6L, 2L, 3L ); SetRGB4( &(SurfScrn->ViewPort),18L, 0L, 0L, 0L ); SetRGB4( &(SurfScrn->ViewPort),19L, 9L, 7L, 6L ); } void ClrWindow(drawaxis) bool drawaxis; { long BkColAdj; /* background color adjusted for number of bit planes */ BkColAdj = (BackColor * NumColors) / 32; SetRast(rp, BackColor); /* clear the window to colour 0 */ SetAPen(rp, WinFgCol ); /* * Draw axis on screen */ if( drawaxis) { Move( rp, 0, WinVOrig); /* x axis */ Draw( rp, (long)SurfWinDef.Width, (long)WinVOrig ); Move( rp, WinHOrig, 0); /* y axis */ Draw( rp, (long)WinHOrig, (long)SurfWinDef.Height ); } } void DrawLine( x1, y1, x2, y2, mode ) int x1, y1, x2, y2; int mode; { SetDrMd( rp, mode ); Move( rp, (long)UCntrX(x1), (long)UCntrY(y1)); Draw(rp, (long)UCntrX(x2), (long)UCntrY(y2) ); } void PaintPoint(x,y,forecolor) short x, y; float forecolor; { long shade; shade = forecolor * (NumColors-1); if( shade >= NumColors) { shade = NumColors-1; } else if ( shade < 0 ) { shade = 0; } SetAPen( rp, shade ); WritePixel( rp, (long)UCntrX(x), (long)UCntrY(y)); } void DrawPnt( x, y, op ) int x, y, op; { x = UCntrX(x); y = UCntrY(y); SetDrMd(rp, op ); RectFill( rp, (long)x, (long)y, (long)x, (long)y); } void DrawSqr(x, y, op ) int x, y, op; { x = UCntrX(x); y = UCntrY(y); SetDrMd(rp, op ); RectFill( rp, x - 2L, y -2L, x+ 2L, y+2L ); } void DrawRhomShade( poly) Rhomboid *poly; { int i; int shade; long backcolor, forecolor; shade = (int)((poly->intensity) * ColorMax); if( shade > ColorMax) { shade = ColorMax; } backcolor = shade >> 3; forecolor = backcolor +1; if( forecolor >= NumColors ) { forecolor = backcolor; } SetDrMd( rp, JAM2); SetAPen( rp, forecolor ); SetBPen( rp, backcolor ); SetAfPt( rp, GrayPat[ shade & DitherMask ], 2); AreaMove( rp, UCntrX(poly->pt[0].x), UCntrY(poly->pt[0].y)); for( i = 1; i < 4; i++ ) { AreaDraw( rp, UCntrX(poly->pt[i].x), UCntrY(poly->pt[i].y) ); } AreaEnd(rp); SetAfPt( rp, GrayPat[8], 2); /* reset back to solid */ } void DrawRhomFrame( inlist ) ScrnPair inlist[]; { int i; SetDrMd( rp, JAM1); SetAPen( rp, 0L ); SetOPen( rp, WinFgCol ); AreaMove( rp, UCntrX(inlist[0].x), UCntrY(inlist[0].y)); for( i = 1; i < 4; i++ ) { AreaDraw( rp, UCntrX(inlist[i].x), UCntrY(inlist[i].y) ); } AreaEnd(rp); BNDRYOFF( rp ); /* turn off outlining */ } SwitchBox() { struct IntuiMessage mycopy, *orig; RefreshGadgets(SurfWinDef.FirstGadget, SurfWin, NULL ); while(1) { long wakeupmask; wakeupmask = Wait( SignalMask ); /* * for now, we ignore the wakeupmask, * just read messages from each. if I notice a performance problem, * I'll fix it then */ /* * handle messages for the control window */ while( orig =(struct IntuiMessage *) GetMsg( CntrlWin->UserPort ) ) { mycopy = *orig; ReplyMsg( orig ); switch( mycopy.Class ) { case MENUPICK: MenuHandler( mycopy.Code ); break; case GADGETUP: GadgetHandler( (struct Gadget*)mycopy.IAddress ); break; case CLOSEWINDOW: return; default: break; } } /* * handle the button window */ while( orig =(struct IntuiMessage *) GetMsg( GadWin->UserPort ) ) { mycopy = *orig; ReplyMsg( orig ); switch( mycopy.Class ) { case GADGETUP: GadgetHandler( (struct Gadget*)mycopy.IAddress ); RefreshGadgets(SurfWinDef.FirstGadget, SurfWin, NULL ); break; default: break; } } /* * handle messages for the other window */ while( orig =(struct IntuiMessage *) GetMsg( SurfWin->UserPort ) ) { mycopy = *orig; ReplyMsg( orig ); switch( mycopy.Class ) { case MOUSEBUTTONS: HandleMButtons(&mycopy); break; case INTUITICKS: HandleTicks(&mycopy); break; case MOUSEMOVE: break; default: break; } } } } /* * display error messages inside a requestor */ OutErr(errstr) char *errstr; { static struct IntuiText errtext = { -1, -1, JAM1, 10, 10, NULL, NULL, NULL }; static struct IntuiText negtext = { -1, -1, JAM1, 80, 20, NULL,(UBYTE *)"Onwards", NULL }; errtext.IText = (UBYTE *)errstr; WBenchToFront(); AutoRequest(CntrlWin, &errtext, NULL, &negtext, NULL, NULL, 8*strlen(errstr)+ 40, 60 ); WindowToFront( CntrlWin ); } \Rogue\Monster\ else echo "will not over write ./scrnops.c" fi if `test ! -s ./surf.lnk` then echo "writing ./surf.lnk" cat > ./surf.lnk << '\Rogue\Monster\' ROOT lib:c.o scrnio.o scrnops.o scrndef.o main.o gadgetdef.o menudef.o graypat.o mouse.o gadgetuse.o bezpt.o revolve.o control.o poly.o fasttrig.o readilbm.o writeilbm.o packer.o mapstuff.o mapcalc.o getfilenames.o mapimgpix.o LIBRARY LIB:lcmffp.lib Lib:lc.lib LIB:amiga.lib TO Surf verbose nodebug \Rogue\Monster\ else echo "will not over write ./surf.lnk" fi if `test ! -s ./writeilbm.c` then echo "writing ./writeilbm.c" cat > ./writeilbm.c << '\Rogue\Monster\' #include <stdio.h> #include <exec/types.h> #include <intuition/intuition.h> #include <graphics/gfxmacros.h> #ifdef MANX #include <functions.h> #endif #include "mytypes.h" extern int PackRow(); /* * following definitions cut from ilbm.h file */ typedef UBYTE Masking; /* Choice of masking technique.*/ #define mskNone 0 #define mskHasMask 1 #define mskHasTransparentColor 2 #define mskLasso 3 typedef UBYTE Compression; /* Choice of compression algorithm applied to * each row of the source and mask planes. "cmpByteRun1" is the byte run * encoding generated by Mac's PackBits. See Packer.h . */ #define cmpNone 0 #define cmpByteRun1 1 /* Aspect ratios: The proper fraction xAspect/yAspect represents the pixel * aspect ratio pixel_width/pixel_height. * * For the 4 Amiga display modes: * 320 x 200: 10/11 (these pixels are taller than they are wide) * 320 x 400: 20/11 * 640 x 200: 5/11 * 640 x 400: 10/11 */ #define x320x200Aspect 10 #define y320x200Aspect 11 #define x320x400Aspect 20 #define y320x400Aspect 11 #define x640x200Aspect 5 #define y640x200Aspect 11 #define x640x400Aspect 10 #define y640x400Aspect 11 /* A BitMapHeader is stored in a BMHD chunk. */ typedef struct { UWORD w, h; /* raster width & height in pixels */ WORD x, y; /* position for this image */ UBYTE nPlanes; /* # source bitplanes */ Masking masking; /* masking technique */ Compression compression; /* compression algoithm */ UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/ UWORD transparentColor; /* transparent "color number" */ UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */ WORD pageWidth, pageHeight; /* source "page" size in pixels */ } BitMapHeader; /* RowBytes computes the number of bytes in a row, from the width in pixels.*/ #define RowBytes(w) (((w) + 15) >> 4 << 1) #define IDSIZE 4 WriteIlbm( filename, win, scrn,packflag ) char *filename; struct NewWindow *win; struct NewScreen *scrn; bool packflag; { FILE *ofile; long formpos; /* position of length following 'FORM' */ long formsize; struct ViewPort *vp; ofile = fopen(filename,"w"); if( !ofile ) { return; } fwrite("FORM", IDSIZE, 1, ofile); formpos = ftell( ofile ); fwrite( &formsize, sizeof(formsize), 1, ofile); /* will be rewritten */ fwrite( "ILBMBMHD", IDSIZE*2, 1, ofile ); { BitMapHeader bmhdr; long bmhdrsize; static UBYTE xaspect[2][2]= { { x320x200Aspect, x320x400Aspect }, { x640x200Aspect, x640x400Aspect }}; static UBYTE yaspect[2][2]= { { y320x200Aspect, y320x400Aspect }, { y640x200Aspect, y640x400Aspect }}; int wx, wy; bmhdrsize = 20; fwrite( &bmhdrsize, sizeof(bmhdrsize), 1, ofile); bmhdr.x = bmhdr.y = 0; bmhdr.w = win->Width; bmhdr.h = win->Height; bmhdr.nPlanes = scrn->Depth; bmhdr.masking = mskNone; bmhdr.compression = packflag ?cmpByteRun1: cmpNone; bmhdr.pad1 = 0; wx = (scrn->Width == 320)? 0: 1; wy = (scrn->Height == 200)? 0: 1; bmhdr.xAspect = xaspect[wx][wy]; bmhdr.yAspect = yaspect[wx][wy]; bmhdr.pageHeight = win->Height; bmhdr.pageWidth = scrn->Width; bmhdr.transparentColor = 0; fwrite(&bmhdr, bmhdrsize, 1, ofile ); } fwrite("CMAP",IDSIZE, 1, ofile); vp = &win->Screen->ViewPort; { long cmapsize; long i; UWORD value; UBYTE col[3]; int numentries; numentries = (1<< scrn->Depth ); cmapsize = numentries*3; fwrite( &cmapsize, sizeof(cmapsize), 1,ofile); for( i = 0; i < numentries; i++ ) { value = GetRGB4(vp->ColorMap, i); col[2] = (value & 0xf) << 4; /* blue */ col[1] = value & 0xf0; /* green */ col[0] = (value & 0xf00) >> 4; /* red */ fwrite(col, 3, 1, ofile); } } fwrite("CAMG", IDSIZE, 1, ofile); { long viewmode; long viewmodesize; viewmodesize = sizeof(viewmode); viewmode = scrn->ViewModes; fwrite(&viewmodesize, sizeof(viewmodesize), 1, ofile); fwrite(&viewmode, sizeof(viewmode), 1, ofile ); } fwrite("BODY", IDSIZE,1, ofile); { struct BitMap *bm; long bodypos, bodysize; UBYTE *bmd[16]; /* assume as many as 16 bit planes :-) */ int row; int plane; int rowlength; /* in bytes */ char outbuff[200]; /* largest enough for a row 1600 bits wide */ bodypos = ftell(ofile); fwrite( &bodysize, sizeof(bodysize), 1, ofile); bm = vp->RasInfo->BitMap; rowlength = RowBytes(scrn->Width); for( plane = 0; plane < scrn->Depth; plane++ ) { bmd[plane] = bm->Planes[plane] + rowlength * win->TopEdge; } /* * write actual bitplanes */ for( row = 0; row < win->Height; row++ ) { for( plane = 0; plane < scrn->Depth; plane++ ) { if( packflag ) { int packedsize; packedsize = PackRow(bmd[plane],outbuff, rowlength ); fwrite(outbuff, packedsize, 1, ofile); } else { fwrite(bmd[plane], rowlength, 1, ofile ); } bmd[plane] += rowlength; } } bodysize = ftell(ofile) -( bodypos + 4); /* * fill out body to make even */ if( bodysize & 1 ) { fputc(0,ofile); bodysize++; } formsize = ftell(ofile) -( formpos + 4); fseek( ofile, bodypos, 0L ); fwrite( &bodysize, sizeof(bodysize), 1, ofile); } fseek( ofile, formpos, 0L ); fwrite( &formsize, sizeof(formsize), 1, ofile); fclose(ofile); } \Rogue\Monster\ else echo "will not over write ./writeilbm.c" fi echo "Finished archive 1 of 3" # if you want to concatenate archives, remove anything after this line exit -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page "I can't tell the difference between ABC News and Hill Street Blues" -Bono