#include #include "mytypes.h" #include "poly.h" #include "bezpt.h" #include "revolve.h" #include "readilbm.h" #include "mapstuff.h" #include "menuexp.h" #define FarRight 1e6 #define FarLeft -1e6 #define FarTop 0x7fff #define FarBottom -0x7fff #ifndef MANX #include #define ceil SPCeil #define floor SPFloor #define fabs SPAbs #endif typedef struct { float left, right; } Hedge; static float *BezMapping = null, *RevMapping = null; static float revmin, revdiff, bezmin, bezdiff; /* * given the ptlist of a polygon, find its vertical range */ static void FindVRange(scrnlist, top, bottom) register ScrnPair *scrnlist; short *top, *bottom; { short i; short localtop, localbot; localtop = FarBottom; localbot = FarTop; for( i = 4; i--; scrnlist++ ) { if( localtop < scrnlist->y ) localtop = scrnlist->y; if( localbot > scrnlist->y ) localbot = scrnlist->y; } *top = localtop; *bottom = localbot; } /* * allocate table to store a quick and dirty representation of the * quadrilateral segments */ static Hedge *InitVRange( depth, tabptr, olddepth ) short depth, *olddepth; Hedge *tabptr; { Hedge *edgel, *tab; if( *olddepth < depth || !tabptr ) { if( tabptr ) free( tabptr); tab = (Hedge *) malloc(sizeof(Hedge)*depth); *olddepth = depth; } else { tab = tabptr; } if( !tab ) return( null); for( edgel = tab; depth--; edgel++) { edgel->left = FarRight; edgel->right = FarLeft; } return( tab ); } /* * add line to quadrilateral descriptions */ static void AddVLine( tab, x1, y1, x2, y2 ) Hedge *tab; short x1, y1, x2, y2; { short dy; float curx, slope; /* * want y1 to have smaller value, ie, y1 below y2 */ if( y1 > y2 ) { short temp; temp = y1; y1 = y2; y2 = temp; temp = x1; x1 = x2; x2 = temp; } dy = y2 - y1; tab += y1; if( !dy ) { if ( x1 < x2 ) { short tempx; tempx = x1; x1 = x2; x2 = tempx; } if( x2 < tab->left ) tab->left = x2; if( x1 > tab->right ) tab->right = x1; return; } slope = (float)(x2 - x1)/dy; curx = x1; #define ZipIt(xxx) { if( xxx < tab->left) tab->left = xxx; \ if( xxx > tab->right ) tab->right = xxx; } ZipIt(curx); while( dy--) { curx += slope; tab++; ZipIt(curx); } } static void AdjMapXY( inx, iny, outpair) float inx, iny; ScrnPair *outpair; { float outx, outy; MapXYRatio( inx, iny, &outx, &outy); outpair->y = MapImageH * (bezmin + bezdiff * outy); outpair->x = MapImageV * (revmin + revdiff * outx); /* if( RevAxis == RevX ) { outpair->y = MapImageH * (bezmin + bezdiff * outy); outpair->x = MapImageV * (revmin + revdiff * outx); } else { outpair->x = MapImageH * (bezmin + bezdiff * outy); outpair->y = MapImageV * (revmin + revdiff * outx); } */ } static void ScanCnvQuad( tab, pt) Hedge *tab; ScrnPair pt[]; { register int i; ScrnPair *listb, *liste; liste = pt; listb = liste + 3; for ( i = 4; i--;) { AddVLine( tab, listb->x, listb->y, liste->x, liste->y); listb = liste++; } } static float AverageShade(pts) ScrnPair pts[]; { register Hedge *tab; static Hedge *tabfree = null; static short olddepth = 0; short top, bot; long shade = 0, pixcnt = 0; FindVRange( pts, &top, &bot); tabfree = tab = InitVRange( top - bot + 1, tabfree, &olddepth); if(!tabfree) return(0.0); ScanCnvQuad( tab-bot, pts ); #if DEBUG if( DebugOn ) { printf("AverageShade top is %d, bot = %d\n", top, bot ); } #endif DEBUG while( bot <= top ) { register int hori; int right, left; #if DEBUG if( DebugOn ) { printf("....row %d \t%d -> %d\n", bot, left, right ); } #endif DEBUG left = (int) ceil(tab->left - SingleTinyVal); right = (int)floor(tab->right+ SingleTinyVal); for( hori= left; hori <= right; hori++ ) { shade += GetImgPix( bot, hori); pixcnt++; } /* if( RevAxis == RevX ) { for( hori= left; hori <= right; hori++ ) { shade += GetImgPix( bot, hori); pixcnt++; } } else { for( hori= left; hori <= right; hori++ ) { shade += GetImgPix( hori, bot); pixcnt++; } } */ tab++; bot++; } return( (float)shade / (pixcnt *(15 *16)) ); } /* * mess with the number so truncation doesn't * do nasty things to a float containing an int */ static int NearestInt( afloat ) float afloat; { afloat += ( afloat > 0 )? 1e-2 : -1e-2; return( (int)afloat ); } static void ShadeQuad(tab, top, bot, intensity) register Hedge *tab; short top, bot; float intensity; { short vert; float rowminl, rowminr, rowmaxl, rowmaxr; Hedge *oldtab, *nexttab; for ( vert = bot; nexttab = tab+1, vert <= top; vert++, oldtab = tab, tab++ ) { float hori; float colmin, colmax; float leftmost, rightmost; int ihori, ileftmost, irightmost; ScrnPair MpPnts[4]; #define lefttop MpPnts[0] #define leftbot MpPnts[3] #define righttop MpPnts[1] #define rightbot MpPnts[2] rowminl = (float)vert; rowmaxr = rowmaxl = rowminr = rowminl; if( vert > bot && oldtab->left < tab->left ) { rowminl -= 0.5; } if( vert > bot && oldtab->right > tab->right ) { rowminr -= 0.5; } if( vert < top && nexttab->left < tab->left ) { rowmaxl += 0.5; } if( vert < top && nexttab->right > tab->right ) { rowmaxr += 0.5; } irightmost = NearestInt( tab->right ); rightmost = irightmost; ileftmost = NearestInt( tab->left ); leftmost = ileftmost; if( irightmost < ileftmost ) { irightmost = ileftmost; } for( ihori = leftmost, hori = leftmost; ihori <= irightmost; ihori += 1, hori += 1.0 ) { if( AbortDraw ) { return; } colmin = hori - 0.5; colmax = hori + 0.5; colmin =(colmin > leftmost)?colmin: tab->left; colmax =(colmax < rightmost)?colmax: tab->right; AdjMapXY( colmin, rowmaxl, &lefttop, MP_XMIN| MP_YMAX); AdjMapXY( colmax, rowmaxr, &righttop, MP_XMAX| MP_YMAX); AdjMapXY( colmin, rowminl, &leftbot, MP_XMIN| MP_YMIN); AdjMapXY( colmax, rowminr, &rightbot, MP_XMAX| MP_YMIN); PaintPoint(ihori, vert, AverageShade(MpPnts) *intensity); } } #undef lefttop #undef righttop #undef rightbot #undef leftbot } void DrawRhomMap(mpr) MapRhomboid *mpr; { short top, bottom; static Hedge *tab = null; static short olddepth = 0; CalcMapConsts( mpr->rhom.pt ); FindVRange( mpr->rhom.pt, &top, &bottom ); tab = InitVRange( top - bottom + 1, tab, &olddepth ); if(!tab) return; ScanCnvQuad( tab -bottom, mpr->rhom.pt ); bezmin = BezMapping[mpr->bezindex];/* make it global */ bezdiff = BezMapping[mpr->bezindex+1] - bezmin; revmin = RevMapping[mpr->revindex]; revdiff = RevMapping[mpr->revindex+1] - revmin; #if DEBUG if( DebugOn ) { DBMAP(mpr->rhom.pt, mpr->bezindex, mpr->revindex); } #endif DEBUG ShadeQuad(tab, top, bottom, mpr->rhom.intensity); } #ifdef DEBUG DBMAP(ptlist, bindex, rindex) ScrnPair ptlist[]; short bindex, rindex; { int i; printf("...................................\n"); for( i = 0; i < 4; i++ ) { printf("%10d", ptlist[i].x); }; printf("\n"); for( i = 0; i < 4; i++ ) { printf("%10d", ptlist[i].y); }; printf("\n"); printf(" bezmin %f bezdiff %f index = %d \n", bezmin, bezdiff, bindex ); printf(" revmin %f revdiff %f index = %d \n", revmin, revdiff, rindex ); } #endif DEBUG /* * return true if image mappings could not be performed * false if successful */ bool InitMapping() { float *vfmptr; float totallen = 0, scaling; short numvslices; if( BezMapping ) free( BezMapping ); if( RevMapping ) free( RevMapping ); /* * compute width of each bezier segment */ numvslices = BezMesh*GetNumSegs() +1; vfmptr = BezMapping = (float *) malloc(sizeof(float) * numvslices); if( !BezMapping ) return(true); *vfmptr++ = totallen = 0.0; ResetActSeg(); do { float t, ffromx, ftox, ffromy, ftoy; int i; InitCalcBez(); for( i = 1, ffromx = StartPtX(ActSeg), ffromy = StartPtY(ActSeg); i <= BezMesh; i++, ffromx = ftox, ffromy = ftoy ) { float diffx, diffy; t = (float)i/BezMesh; CalcBezPt( t, &ftox, &ftoy ); diffx = ftox - ffromx; diffy = ftoy - ffromy; totallen += sqrt( diffx * diffx + diffy * diffy ); *vfmptr++ = totallen; } NextSeg(); } while( ActSeg); /* * convert scale floating point values to integer pixel positions */ scaling = 1.0 / totallen; for( vfmptr = BezMapping; numvslices; numvslices--, vfmptr++ ) { *vfmptr *= scaling; } /* * compute height of each revolution segment */ RevMapping = (float *) malloc( sizeof(float) * (RevMesh + 1)); if( !RevMapping ) return( true ); { short i; for( i = 0; i <= RevMesh; i++ ) { RevMapping[i] = ((float) i)/RevMesh; } } return(false); }